451
Mobile SDK 開発ガイド Salesforce Mobile SDK 4.3 (Android ネイティ ブ、iOS ネイティブ、およびハイブリッ ) @salesforcedocs 最終更新日: 2016/08/22

Mobile SDK 開発ガイド

  • Upload
    vokhanh

  • View
    324

  • Download
    6

Embed Size (px)

Citation preview

Mobile SDK 開発ガイドSalesforce Mobile SDK 4.3 (Android ネイティブ、iOS ネイティブ、およびハイブリッド)

@salesforcedocs最終更新日: 2016/08/22

本書の英語版と翻訳版で相違がある場合は英語版を優先するものとします。

© Copyright 2000–2016 salesforce.com, inc. All rights reserved. Salesforce およびその他の名称や商標は、salesforce.com,

inc. の登録商標です。本ドキュメントに記載されたその他の商標は、各社に所有権があります。

目次

第 1 章: このドキュメントについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

モバイル開発の概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Salesforce1 のカスタマイズかカスタムアプリケーションの作成か . . . . . . . . . . . . . . . . . . 3このガイドの内容 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

バージョン . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5フィードバックの送信 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

第 2 章: Salesforce Mobile SDK 開発の概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

ネイティブ、HTML5、およびハイブリッド開発について . . . . . . . . . . . . . . . . . . . . . . . . 8クイックスタート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

第 3 章: Mobile SDK 4.3 の新機能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

第 4 章: 最近のリリースの新機能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

第 5 章: Mobile SDK 4.3 for Android および iOS の使用開始 . . . . . . . . . . . . . . . . . . . 16

Developer Edition 環境か Sandbox 環境か . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17Android および iOS の開発の前提条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18Force.com のサインアップ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19接続アプリケーションの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

接続アプリケーションを作成する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20Mobile SDK for Android および iOS のインストール . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

Mobile SDK npm パッケージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23Mobile SDK GitHub リポジトリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

Mobile SDK サンプルアプリケーション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27サンプルアプリケーションのインストール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

第 6 章: Mobile SDK Labs へようこそ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

Salesforce Mobile SDK の React Native . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32React Native アプリケーション用の Mobile SDK ネイティブモジュール . . . . . . . . . . 33React Native を使用した Mobile SDK サンプルアプリケーション . . . . . . . . . . . . . . . 36ログインの延期 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38バイナリコンテンツのアップロード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

Polymer を使用するモバイル UI 要素 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40force_selector_list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41force-selector-relatedlist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41force-sobject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42force-sobject-collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42force-sobject-layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42force-sobject-relatedlists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

force-sobject-store . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43force-ui-app . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43force-ui-detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43force-ui-list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44force-ui-relatedlist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

第 7 章: ネイティブ iOS の開発 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

iOS ネイティブクイックスタート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46ネイティブ iOS の要件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46forceios を使用した iOS プロジェクトの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

Xcode プロジェクトのテンプレートアプリケーションを実行する . . . . . . . . . . . . . 48CocoaPods と Mobile SDK の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48ネイティブ iOS アプリケーションの開発 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

ログインとパスコードについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51メモリ管理について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52アプリケーションフローの概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52SalesforceSDKManager および SmartStoreSDKManager クラス . . . . . . . . . . . . . . . . . 53AppDelegate クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59ビューコントローラについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63RootViewController クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63Salesforce REST API について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65認証エラーの処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

チュートリアル: ネイティブ iOS Warehouse アプリケーションの作成 . . . . . . . . . . . . . . 78ネイティブ iOS アプリケーションを作成する . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80リスト画面をカスタマイズする . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85詳細画面を作成する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

iOS サンプルアプリケーション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

第 8 章: ネイティブ Android の開発 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

Android ネイティブクイックスタート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102ネイティブ Android の要件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102Android プロジェクトの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103Android Studio でのサンプルプロジェクトの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

Android プロジェクトファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106ネイティブ Android アプリケーションの開発 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

Android アプリケーションの構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107ネイティブ API パッケージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109ネイティブクラスの概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109パスコードの使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120リソースの処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121REST API の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124認証されていない REST 要求 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126ネイティブ Android アプリケーションのログインの延期 . . . . . . . . . . . . . . . . . . . 127Android テンプレートアプリケーション: 詳細 . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

目次

チュートリアル: ネイティブ Android Warehouse アプリケーションの作成 . . . . . . . . . . 132前提条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132ネイティブ Android アプリケーションを作成する . . . . . . . . . . . . . . . . . . . . . . . . 134リスト画面をカスタマイズする . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137詳細画面を作成する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

Android サンプルアプリケーション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

第 9 章: HTML5 およびハイブリッド開発 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151HTML5 および JavaScript の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151HTML5 の開発要件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151マルチデバイス戦略 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

HTML5 開発ツール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155Visualforce を使用した HTML5 コンテンツの配信 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155Salesforce データへのアクセス: コントローラと API . . . . . . . . . . . . . . . . . . . . . . . . . . 156ハイブリッドアプリケーションのクイックスタート . . . . . . . . . . . . . . . . . . . . . . . . . . 158ハイブリッドアプリケーションの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

ハイブリッド開発について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160Cordova を使用したハイブリッドアプリケーションの開発 . . . . . . . . . . . . . . . . . 160ハイブリッドリモートアプリケーションの開発 . . . . . . . . . . . . . . . . . . . . . . . . . 164ハイブリッドサンプルアプリケーション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166ContactExplorer ハイブリッドサンプルの実行 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

モバイルデバイスでのハイブリッドアプリケーションのデバッグ . . . . . . . . . . . . . . . . 181Android デバイスのハイブリッドアプリケーションのデバッグ . . . . . . . . . . . . . . . 181iOS デバイスで実行されているハイブリッドアプリケーションのデバッグ . . . . . . 182

iOS 7 ハイブリッドアプリケーションでのステータスバーの制御 . . . . . . . . . . . . . . . . . 183ハイブリッドアプリケーションの JavaScript ファイル . . . . . . . . . . . . . . . . . . . . . . . . . 183バージョン設定および JavaScript ライブラリの互換性 . . . . . . . . . . . . . . . . . . . . . . . . . 184ハイブリッドアプリケーションでのセッション管理 . . . . . . . . . . . . . . . . . . . . . . . . . . 186ログインの延期 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190Android ハイブリッドアプリケーションからの SmartStore と SmartSync の削除 . . . . . . . 191例: 適切な JavaScript ライブラリの提供 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

第 10 章: オフライン管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193

SmartStore を使用したオフラインデータの安全な保存 . . . . . . . . . . . . . . . . . . . . . . . . 194SmartStore について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195ハイブリッドおよびネイティブアプリケーションでの SmartStore の有効化 . . . . . 198既存の Android アプリケーションへの SmartStore の追加 . . . . . . . . . . . . . . . . . . . 198スープの登録 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199インデックスパスでの配列の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202スープの入力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204スープからのデータの取得 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207スマート SQL クエリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216全文検索クエリの使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217

目次

クエリ結果の処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222データの挿入、更新、および更新/挿入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223大きいスープ要素での外部ストレージの使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . 227スープ要素の削除 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230スープの管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231グローバル SmartStore の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238SmartStore インスペクタを使用したテスト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239擬似 SmartStore の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240

SmartSync を使用した Salesforce オブジェクトへのアクセス . . . . . . . . . . . . . . . . . . . . 242ネイティブアプリケーションでの SmartSync の使用 . . . . . . . . . . . . . . . . . . . . . . 242ハイブリッドアプリケーションでの SmartSync の使用 . . . . . . . . . . . . . . . . . . . . 268

第 11 章: ファイルとネットワーキング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322

アーキテクチャ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323ファイルのダウンロードと共有の管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323ファイルのアップロード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324暗号化とキャッシュ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324Android アプリケーションでのファイルの使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324

要求キューの管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325iOS ネイティブアプリケーションでのファイルの使用 . . . . . . . . . . . . . . . . . . . . . . . . 326

要求の管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326ハイブリッドアプリケーションでのファイルの使用 . . . . . . . . . . . . . . . . . . . . . . . . . 327

第 12 章: 転送通知と Mobile SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328

転送通知について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329ハイブリッドアプリケーションでの転送通知の使用 . . . . . . . . . . . . . . . . . . . . . . . . . 329

コードの変更 (ハイブリッド) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329Android での転送通知の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330

GCM (Android) 用に接続アプリケーションを設定する . . . . . . . . . . . . . . . . . . . . . . 331コードの変更 (Android) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331

iOS での転送通知の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332APNS (iOS) 用に接続アプリケーションを設定する . . . . . . . . . . . . . . . . . . . . . . . . 333コードの変更 (iOS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334

第 13 章: モバイルアプリケーションでの認証、セキュリティ、ID . . . . . . . . . . . 337

OAuth の用語 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338OAuth2.0 認証フロー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338

OAuth 2.0 ユーザエージェントフロー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339OAuth 2.0 更新トークンフロー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340範囲パラメータの値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341ID URL の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342Android アプリケーションでのカスタムログインサーバの設定 . . . . . . . . . . . . . . 348iOS アプリケーションでのカスタムログインサーバの設定 . . . . . . . . . . . . . . . . . 349iOS アプリケーションでの設定アイコンの非表示 . . . . . . . . . . . . . . . . . . . . . . . . 351

目次

OAuth トークンの取り消し . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352Android ネイティブアプリケーションでの更新トークンの取り消し . . . . . . . . . . . 353

接続アプリケーション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353PIN セキュリティについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354

OAuth 2.0 サイトおよび Force.com サイトを使用したポータル認証 . . . . . . . . . . . . . . . 354Salesforce Mobile SDK アプリケーションでの MDM の使用 . . . . . . . . . . . . . . . . . . . . . . 355

第 14 章: Mobile SDK アプリケーションでの Communities の使用 . . . . . . . . . . . . 359

コミュニティと Mobile SDK アプリケーション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360「API の有効化」プロファイルを設定する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360権限セットを設定する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361API アクセス権をユーザに付与する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362ログインエンドポイントを設定する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362コミュニティのブランド設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364コミュニティのログイン、ログアウト、およびセルフ登録ページのカスタマイズ . . . . 365コミュニティでの外部認証の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366

外部認証プロバイダについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366コミュニティ URL パラメータの使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367Scope パラメータの使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368Facebook 認証プロバイダの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370Salesforce 認証プロバイダの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373OpenID Connect 認証プロバイダの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376

例: Mobile SDK アプリケーションからアクセスできるようにコミュニティを設定する . . 379プロファイルに権限を追加する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379コミュニティを作成する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380コミュニティに API ユーザプロファイルを追加する . . . . . . . . . . . . . . . . . . . . . . 380新しい取引先責任者およびユーザを作成する . . . . . . . . . . . . . . . . . . . . . . . . . . . 381新しいコミュニティログインをテストする . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382

例: Facebook 認証できるようにコミュニティを設定する . . . . . . . . . . . . . . . . . . . . . . 383Facebook アプリケーションを作成する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383Salesforce 認証プロバイダを定義する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383Facebook アプリケーションを設定する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384認証プロバイダの Apex クラスをカスタマイズする . . . . . . . . . . . . . . . . . . . . . . 385Salesforce コミュニティを設定する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386

第 15 章: Mobile SDK でのマルチユーザのサポート . . . . . . . . . . . . . . . . . . . . . . . 387

マルチユーザのサポートについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388マルチユーザのサポートの実装 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388

Android ネイティブ API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390iOS ネイティブ API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396ハイブリッド API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

第 16 章: 以前のリリースからの移行 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402

Android アプリケーションを 4.2 から 4.3 に移行する . . . . . . . . . . . . . . . . . . . . . . . . . 403

目次

iOS アプリケーションを 4.2 から 4.3 に移行する . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403ハイブリッドアプリケーションを 4.2 から 4.3 に移行する . . . . . . . . . . . . . . . . . . . . . 403以前のリリースからの移行 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

Android アプリケーションを 4.1 から 4.2 に移行する . . . . . . . . . . . . . . . . . . . . . . 403iOS アプリケーションを 4.1 から 4.2 に移行する . . . . . . . . . . . . . . . . . . . . . . . . . 404ハイブリッドアプリケーションを 4.1 から 4.2 に移行する . . . . . . . . . . . . . . . . . . 404Android アプリケーションを 4.0 から 4.1 に移行する . . . . . . . . . . . . . . . . . . . . . . 404iOS アプリケーションを 4.0 から 4.1 に移行する . . . . . . . . . . . . . . . . . . . . . . . . . 404ハイブリッドアプリケーションを 4.0 から 4.1 に移行する . . . . . . . . . . . . . . . . . . 404Android アプリケーションを 3.3 から 4.0 に移行する . . . . . . . . . . . . . . . . . . . . . . 405iOS アプリケーションを 3.3 から 4.0 に移行する . . . . . . . . . . . . . . . . . . . . . . . . . 405ハイブリッドアプリケーションを 3.3 から 4.0 に移行する . . . . . . . . . . . . . . . . . 405ハイブリッドアプリケーションを 3.2 から 3.3 に移行する . . . . . . . . . . . . . . . . . 405Android ネイティブアプリケーションを 3.2 から 3.3 に移行する . . . . . . . . . . . . . 406iOS ネイティブアプリケーションを 3.2 から 3.3 に移行する . . . . . . . . . . . . . . . . 406Android ネイティブアプリケーションを 3.1 から 3.2 に移行する . . . . . . . . . . . . . . 407ハイブリッドアプリケーションを 3.1 から 3.2 に移行する . . . . . . . . . . . . . . . . . . 408iOS ネイティブアプリケーションを 3.1 から 3.2 に移行する . . . . . . . . . . . . . . . . . 408ハイブリッドアプリケーションを 3.0 から 3.1 に移行する . . . . . . . . . . . . . . . . . . 409Android ネイティブアプリケーションを 3.0 から 3.1 に移行する . . . . . . . . . . . . . . 410iOS ネイティブアプリケーションを 3.0 から 3.1 に移行する . . . . . . . . . . . . . . . . . 410

第 17 章: リファレンス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412

REST API リソース . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413iOS アーキテクチャ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414

iOS のネイティブ REST API クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414Android アーキテクチャ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417

Android パッケージおよびクラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417Android リソース . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419

Files API リファレンス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422FileRequests メソッド (Android) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422SFRestAPI (Files) カテゴリ — 要求メソッド (iOS) . . . . . . . . . . . . . . . . . . . . . . . . . . . 428ハイブリッドアプリケーションの Files メソッド . . . . . . . . . . . . . . . . . . . . . . . . . 435

forceios パラメータ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441forcedroid パラメータ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443

目次

第 1 章 このドキュメントについて

わずか 10 年足らずで、モバイルデバイスは私たちの生活と仕事を劇的に変えました。即興動画からモバイル地理位置情報、オンラインショッピングに至るまで、あ

トピック:

• モバイル開発の概要

らゆる場所で個人用モバイルデバイスを使用してコンテンツの作成や閲覧が行われています。企業の従業員もスマートデバイスを使用して、顧客と連絡を取ったり、

• Salesforce1 のカスタマイズかカスタム

同僚とやりとりをしたり、ソーシャルネットワークで世間の人々と関わったりしています。

アプリケーションの作成か エンタープライズ IT 部門では、モバイルでのやりとりの急増に伴い、ソフトウェア

サービスでの迅速な対応が必要になっています。Salesforce は、このニーズに対応す• このガイドの内容 る Salesforce App Cloud を提供しています。このクラウドは新世代のモバイル OS をサ• フィードバックの

送信ポートし、電話、タブレット、ウェアラブルなどさまざまなフォーム要素に対応するとともに、信頼性、可用性、セキュリティを実現しています。そのテクノロジによって、ユーザはカスタムアプリケーションを構築し、あらゆるシステムからのデータを接続し、エンタープライズをあらゆる場所から管理することができます。

1

モバイル開発の概要

Salesforce App Cloudでは、2 つの方法で、エンタープライズ対応のモバイルアプリケーションを構築およびリリースできます。• Salesforce1 アプリケーションは、Apple AppStore および Google Play Store から入手可能で、Force.com のシステム

管理者と開発者がアプリケーションを構築し、従業員に配布する最も速い方法です。システム管理者向けのシンプルなポイント & クリックツールと、高度な開発者向けの Lightning Web 開発プラットフォームがあります。

• Salesforce Mobile SDKで構築するカスタムアプリケーションでは、開発者が、従業員、顧客、パートナー向けにカスタマイズされたユーザ環境を備えた新しいモバイルアプリケーションを構築できます。これらのアプリケーションの構築には、ネイティブテクノロジと Web テクノロジのいずれかを選択でき、Salesforce1アプリケーションと同じエンタープライズレベルの信頼性とセキュリティを実現できます。

Salesforce Mobile SDK には、iOS、Android、Windows 10 (ベータ) を対象としたモジュール形式のアプリケーションアーキテクチャが用意されています。このライブラリが、セキュアなデータアクセス、オフラインストレージ、データ同期など、モバイルアプリケーションの一般的な機能を実装します。Mobile SDK アーキテクチャにより、開発者は、機能について妥協することなく、好みのネイティブフレームワークおよびハイブリッドフレームワークを使用できます。

Mobile SDK アーキテクチャ

Mobile SDK と Force.com の組み合わせにより、次のものを備えた完全なモバイルプラットフォームが提供されます。エンタープライズ ID およびセキュリティ

Mobile SDKには、Salesforce接続アプリケーションポリシーの完全な実装が含まれているため、すべてのユーザが安全で簡単にデータにアクセスできます。SAML と高度な認証フローがサポートされているため、システム管理者は常にデータアクセスを完全に制御できます。

SmartStore 暗号化データベースモバイルデータベースは、応答性が高く、どのようなネットワーク状態でも動作するアプリケーションを構築するのに便利です。SmartStoreを使用することにより、柔軟なデータモデルに対応し、データをローカ

2

モバイル開発の概要このドキュメントについて

ルで簡単に保存および取得できます。また、AES-256 暗号化が採用され、データが保護された状態で維持されます。

SmartSync データ同期SmartSync は、オフラインデータベースと Salesforce クラウド間でデータを同期するシンプルな API を提供します。SmartSync を使用することによって、開発者は、複雑な同期ロジックは Mobile SDK に任せて、アプリケーションの UI とビジネスロジックに集中できます。

モバイルサービスMobile SDKに Force.com プラットフォームを利用すれば、転送通知、地理位置情報、分析、コラボレーションツール、ビジネスロジックなどの幅広いサービスがクラウドで提供されます。これらのサービスにより、モバイルアプリケーションが大幅に強化されるとともに、開発時間が短縮されます。

Salesforce Communities

Salesforce Communities とMobile SDKを併用すれば、開発者が顧客やパートナー向けのモバイルアプリケーションを構築できます。これらのアプリケーションでも、従業員アプリケーションと同様のエンタープライズ機能と信頼性を利用できます。

ネイティブとハイブリッドMobile SDK により、iOS と Android で任意のテクノロジ (ネイティブアプリケーション、React Native アプリケーション、Cordova ベースのハイブリッドアプリケーション) を選択できます。Mobile SDK for Windows 10 も近日公開されます。

Salesforce1のカスタマイズかカスタムアプリケーションの作成か

Salesforce モバイルユーザ用の機能を開発する場合には、2 つのオプションがあります。このマニュアルではMobile SDK開発のみを取り上げていますが、Mobile SDKアプリケーションで作成されたSalesforce1アプリケーションとカスタムアプリケーションにはいくつかの相違点があります。Salesforce1 についての詳細は、developer.salesforce.com/docs を参照してください。

Salesforce1 のカスタマイズ• 定義済みのユーザインターフェースがある。• Salesforce データにフルアクセスできる。• Salesforce App Cloud で開発された機能と統合された環境を作成できる。• アクションバーにより、独自のアプリケーション/機能を含める方法が提供される。• ポイント & クリックまたはプログラムによるカスタマイズのいずれかを使用して Salesforce1をカスタマイズ

できる。• VisualforceページまたはForce.com Canvaアプリケーションを使用して、プログラムにより機能を追加できる。• Salesforce1のカスタマイズまたはアプリケーションは、Salesforce1ナビゲーションに準拠する。このため、た

とえば Visualforce ページなどをナビゲーションメニューまたはアクションバーからコールできます。• 既存の Salesforce 開発手法 (ポイント & クリックおよびプログラムの両方) を活用できる。• すべての Salesforce エディションに含まれ、Salesforce でサポートされている。

3

Salesforce1 のカスタマイズかカスタムアプリケーションの作成か

このドキュメントについて

カスタムモバイルアプリケーションの開発カスタムアプリケーションは、Salesforce Mobile SDK で作成する独立型アプリケーションの場合と、プレーンHTML5 および JQuery Mobile/Ajax を使用するブラウザアプリケーションの場合があります。カスタムアプリケーションでは、次のことができます。• カスタムユーザ環境を定義する。• ネイティブおよびハイブリッドのローカルアプリケーションで REST API を使用するか、JavaScript Remoting を

使用するハイブリッドアプリケーションで Visualforce を使用して、Salesforce データにアクセスする。HTML5

アプリケーションでは、JQueryMobile および Ajax を使用して同じ操作を行います。• 顧客向け公開用のユーザインターフェースをブランド設定する。• Java for Android または Objective-C for iOS を使用するネイティブ API を使用するか、JavaScript および HTML5 を使

用するハイブリッドコンテナを使用して、スタンドアロンモバイルアプリケーションを作成する (Mobile SDK

のみ)。• Apple App Store や Google Play などのモバイル業界チャネルを使用して、アプリケーションを配布する (Mobile

SDK のみ)。• 複雑なオフライン動作を設定および制御する (Mobile SDK のみ)。• 転送通知を使用する。• 独自の OAuth モジュールを使用して、カスタムセキュリティコンテナを設計する (Mobile SDK のみ)。• Mobile SDK のその他の重要な考慮事項:

– オープンソース SDK は、npm インストーラおよび GitHub から無料でダウンロードできます。ライセンスは必要ありません。

– アプリケーションを外部開発環境 (iOS の場合は Xcode、Android の場合は Android Studio、Windows 10 の場合は Visual Studio) で開発およびコンパイルする必要があります。

– 開発コストは、アプリケーションやプラットフォームによって異なります。

Mobile SDK は、以下を提供することで Force.com クラウドアーキテクチャを Android および iOS アプリケーションに統合します。• JavaScript を介して Salesforce データにアクセスして同期する SmartSync Data Framework

• Salesforce 接続アプリケーションポリシーの実装• 永続化機能や更新機能を含む、OAuth ログイン情報管理• Salesforce REST API のラッパー• ハイブリッドアプリケーション用の Cordova ベースのコンテナ• ハイブリッドアプリケーションのデータ同期• SmartStore を使用した安全なオフラインストレージ• Salesforce Communities のサポート• 複数ユーザログイン間の高速な切り替えのサポート

4

Salesforce1 のカスタマイズかカスタムアプリケーションの作成か

このドキュメントについて

このガイドの内容

このガイドでは、Salesforce Mobile SDK を紹介し、クラウド用モバイルアプリケーションの設計、開発、管理方法について説明します。HTML5 および JavaScript から始まり、ハイブリッドアプリケーション、さらに最終的にはネイティブ開発に至るまで、さまざまなスキルセットを持つユーザ向けの幅広い開発方法を網羅しています。主要機能のチュートリアルも含まれています。ほとんどのチュートリアルは、REST API を使用して Salesforce にアクセスする単純な主従アプリケーションの作成手順を説明しています。次のチュートリアルがあります。• ContactExplorer ハイブリッドサンプルの実行• チュートリアル: ネイティブ Android Warehouse アプリケーションの作成• チュートリアル: ネイティブ iOS Warehouse アプリケーションの作成• チュートリアル: ハイブリッド SmartSync アプリケーションの作成より簡潔でカジュアルなチュートリアルも本書のあちこちにあります。

対象利用者このガイドは、モバイル技術、OAuth2、および REST API について理解している開発者、および Force.com の使用経験がある開発者を主に対象としています。ただし、これに該当しない場合でも心配いりません。このガイドは幅広い利用者に役立つように作成されています。たとえば、組織向けの新しいモバイルアプリケーションを開発しているSalesforceシステム管理者や、Force.comの使用経験がまったくないモバイル開発者でも理解できる内容になっています。

Mobile SDK および Trailheadこのガイドのほとんどの内容は、Trailhead で対話形式で学習できます。Mobile SDK初級トレイルでは、各開発トピックについてオンラインで学習し、対話型の練習問題とクイズを通じてポイントとバッジを獲得します。developer.salesforce.com/trailhead/trail/mobile_sdk_introを参照してください。

メモ: 本書のオンラインバージョンは、developer.salesforce.com/docs で参照できます。

バージョン本書は Salesforce Mobile SDK 4.3 です。

フィードバックの送信

本書に関するご質問またはコメントがある場合や、今後のバージョンで追加するトピックのご提案がある場合、次の方法を利用できます。• SalesforceMobileSDK コミュニティ (plus.google.com/communities) に参加する• Salesforce 開発者ディスカッションフォーラム (developer.salesforce.com/forums) で意見を投稿する• [email protected] に直接メールを送信する

5

このガイドの内容このドキュメントについて

• オンラインドキュメント (developer.salesforce.com/docs/atlas.en-us.mobile_sdk.meta/mobile_sdk/) の各ページの下部にある [フィードバック] ボタンを使用する

6

フィードバックの送信このドキュメントについて

第 2 章 Salesforce Mobile SDK 開発の概要

Salesforce Mobile SDK を使用すると、スタンドアロンモバイルアプリケーション内でForce.com の機能を活用できます。

トピック:

• ネイティブ、HTML5、およびハイ Force.com には、Salesforce クラウドコンピューティング用のわかりやすく生産的なプ

ラットフォームが備えられています。開発者は Force.comを使用して、カスタムオブブリッド開発について ジェクトとカスタム項目、ワークフロールール、Visualforceページ、Apexクラス、ト

リガなどの Salesforce アプリケーションコンポーネントを定義できます。定義したコ• クイックスタートンポーネントは、画期的なブラウザベースのデスクトップアプリケーションに組み込むことができます。Mobile SDKアプリケーションでは、デスクトップアプリケーションと異なり、ブラウザではなくモバイルデバイスのネイティブオペレーティングシステム経由でSalesforce

データにアクセスします。モバイルユーザが満足する生産性の高い操作性を確保するために、オンライン/オフライン状態をシームレスに切り替えられるようMobile SDK

アプリケーションを設定できます。Mobile SDKに着手する前に、モバイル開発のしくみを確認し、重要な Salesforce 開発者リソースについて学習します。

7

ネイティブ、HTML5、およびハイブリッド開発について

Salesforce Mobile SDK では、アプリケーションの開発方法を選択できます。選択できるオプションは、開発スキル、デバイスおよびテクノロジの要件、目的、スケジュールによって変わります。Salesforce Mobile SDK では、3 通りの方法でモバイルアプリケーションを作成できます。• ネイティブアプリケーションは、特定のモバイルプラットフォーム (iOS または Android) に固有であり、それ

ぞれのプラットフォームでサポートされる開発ツールと言語 (iOS の Xcode と Objective-C、Android の Android

Studio と Java など) を使用します。ネイティブアプリケーションは、外観とパフォーマンスは最高ですが、最も多くの開発作業を必要とします。

• HTML5 アプリケーションでは、標準の Web テクノロジ (通常、HTML5、JavaScript および CSS) を使用し、モバイル Web ブラウザを通してアプリケーションを提供します。この「Write Once, Run Anywhere (一度書けば、どこでも実行できる)」というモバイル開発へのアプローチでは、複数のデバイスで動作するクロスプラットフォームのモバイルアプリケーションが作成されます。開発者は、HTML5 と JavaScript のみを使用して高度なアプリケーションを作成することもできますが、セッション管理、安全なオフラインストレージ、ネイティブデバイス機能 (カメラ、カレンダー、通知など) へのアクセスなど、いくつかの難題も残ります。

• ハイブリッドアプリケーションは、Salesforceコンテナ内の Web アプリケーションをラップすることにより、HTML5 Web アプリケーションの開発の容易さをネイティブプラットフォームの機能と結合します。この結合手法では、デバイスのネイティブ機能を利用でき App Store から提供できるアプリケーションが作成されます。また、Salesforce ハイブリッドコンテナを通して提供される Visualforce ページを使用して、ハイブリッドアプリケーションを作成することもできます。

ネイティブアプリケーションネイティブアプリケーションは、使い勝手、機能、全体的なモバイルの操作性の点において最良です。ネイティブアプリケーションでしか実現できないことがいくつかあります。

8

ネイティブ、HTML5、およびハイブリッド開発についてSalesforce Mobile SDK 開発の概要

• 高速グラフィック API — ネイティブプラットフォームでは最も高速なグラフィックを実現できます。限られた要素のみを含む静的画面を表示する場合には重要でないかもしれませんが、大量のデータを使用し、かつすばやい更新を必要とする場合には効果的です。

• 滑らかなアニメーション — 高速グラフィック API と関連し、滑らかなアニメーションを実現する機能です。これは、ゲーム、非常にインタラクティブなレポート、写真や音を変換する強度の演算アルゴリズムには特に重要です。

• 組み込みコンポーネント — カメラ、アドレスブック、地理位置情報、およびデバイスに対してネイティブなその他の機能を、モバイルアプリケーションにシームレスに統合できます。他の重要な組み込みコンポーネントとして、暗号化されたストレージもありますが、これについては後で説明します。

• 使いやすさ — ユーザはネイティブプラットフォームを使い慣れています。この使い慣れた操作感をユーザが期待するネイティブ機能に追加することで、アプリケーションがさらに使いやすくなります。

ネイティブアプリケーションの開発には通常、統合開発環境 (IDE) を使用します。IDE には、作成、デバッグ、プロジェクト管理、バージョン設定用のツール、およびプロの開発者が必要とする他のツールが備えられています。ネイティブアプリケーションの開発は他のアプリケーションより難しいため、これらのツールが必要です。同様に、他の開発シナリオに比べてより高い経験レベルが要求されます。プロの開発者は、実証済みのAPI やフレームワーク、定義済みコンポーネントを使用した簡単な特殊効果、すべてのコードを 1 箇所にまとめることの利点に必ずしも価値を見出しません。

HTML5 アプリケーションHTML5 モバイルアプリケーションは、基本的には小さいモバイルデバイス画面で動作するように設計された 1

つ以上の Web ページです。HTML5 アプリケーション自体はデバイスにとらわれず、最新のどのモバイルブラウザでも開くことができます。コンテンツは Web に存在するため検索可能であり、特定のタイプのアプリケーション (ショッピングなど) では大きな利点となります。HTML5 は、ネイティブ開発やハイブリッド開発に比べて簡単に開始できます。ただし、すべてのモバイルデバイスは、使用可能な画面サイズおよび解像度が独自のアイデアに基づいて構成されています。この多様性により、異なるデバイスやオペレーティングシステムをテストする場合の負担が大きくなります。「Write Once, Run Anywhere」という HTML5 手法の重要な点は、配布とサポートがネイティブアプリケーションに比べて非常に簡単に行えるということです。バグ修正または機能の追加が必要な場合でも、すべてのユーザに対して行われ、導入されます。ネイティブアプリケーションでは開発期間とテスト期間が長くなります。通常コンシューマは、その期間を経た後にストアにログインして新バージョンをダウンロードし、最新の修正を取得する必要があります。HTML5 アプリケーションは、他のアプリケーションよりも開発とサポートが簡単で、最も広範囲にわたるデバイスを使用できますが、次のような欠点もあります。• 安全なオフラインストレージの欠如 — HTML5 ブラウザでは、オフラインのデータベースとキャッシュをサ

ポートしていますが、標準の暗号化はサポートされません。Mobile SDKネイティブアプリケーションでは、3 つの機能をすべて使用できます。

• 使いにくいセキュリティ機能 — 単純なセキュリティ対策を実装する場合でも、モバイル Web アプリケーションでは複雑な課題となることがあります。また、ユーザにとっても不便な場合があります。たとえば、認証を必要とする Web アプリケーションでは、アプリケーションを再起動するたび、またはバックグラウンド状態から戻るたびに、ユーザはログイン情報を入力する必要があります。

9

ネイティブ、HTML5、およびハイブリッド開発についてSalesforce Mobile SDK 開発の概要

• ネイティブ機能の制限 — カメラ、アドレスブック、その他のネイティブ機能は、ほとんどのブラウザのプラットフォームで使用できないか、まったく使用できません。

• ネイティブのデザインの欠如 — HTML5 はネイティブの外観しかエミュレートできず、顧客は使い慣れた複合操作を使用できません。

ハイブリッドアプリケーションハイブリッドアプリケーションは、ネイティブプラットフォーム機能へのアクセスを提供するシンコンテナ内でラップされた HTML5 および JavaScript を使用して作成されます。ハイブリッドアプリケーションのほとんどの部分では、両方のアプリケーションの最良の特性が提供されます。つまり、開発は HTML5 アプリケーションとほぼ同じくらい簡単で、ネイティブアプリケーションのすべての機能が提供されます。また、ハイブリッドアプリケーションでは、JavaScript で SmartSync Data Framework を使用して、次の操作を行うことができます。• Salesforce データをモデル化、クエリ、検索、編集する• オフラインで使用できるように Salesforce データを安全にキャッシュする• ローカルにキャッシュされたデータを Salesforce サーバと同期するネイティブアプリケーションはデバイスにインストールされますが、HTML5 アプリケーションは Web サーバに存在するため、ハイブリッドアプリケーションのファイルがデバイスとサーバのどちらに保存されるのか疑問に思われるかも知れません。ハイブリッドアプリケーションは、ローカルまたはリモートで実装できます。ローカル

HTML と JavaScript のコードは、ネイティブアプリケーションと同様の構造で、モバイルアプリケーションバイナリ内でパッケージ化できます。この場合、REST API および Ajax を使用して、デバイスとクラウド間でデータを移動します。

リモート完全な Web アプリケーションをサーバから実装することもできます (パフォーマンス向上のためオプションとしてキャッシュもできます)。コンテナアプリケーションは、完全なアプリケーションをサーバから取得し、それをブラウザウィンドウに表示します。

ここでは、両方のタイプのハイブリッド開発について説明します。

ネイティブ、HTML5、およびハイブリッドのまとめ次の表に、3 つのモバイル開発シナリオの比較の概要を示します。

ハイブリッドHTML5ネイティブ

HTML、キャンバス、SVGHTML、キャンバス、SVGネイティブ APIグラフィック

高速高速最速パフォーマンス

エミュレートエミュレートネイティブデザインApp StoreWebApp Store配布

はいブラウザに依存はいカメラ

はいいいえはい通知

10

ネイティブ、HTML5、およびハイブリッド開発についてSalesforce Mobile SDK 開発の概要

ハイブリッドHTML5ネイティブ

はいいいえはい連絡先、カレンダー

安全なファイルシステム、共有 SQL

安全ではない、共有 SQL、キー - 値ストア

安全なファイルシステム

オフラインストレージ

はいはいはい地理位置情報

はいはいはいスワイプ

はいはいはいピンチ、スプレッド

オンライン、オフラインほぼオンラインオンライン、オフライン

接続

HTML5、CSS、JavaScriptHTML5、CSS、JavaScriptObjective-C、Java開発手段

クイックスタート

詳細を後で確認したいという方のために、このガイドではネイティブ開発シナリオごとに「クイックスタート」トピックを用意しています。• ハイブリッドアプリケーションのクイックスタート• iOS ネイティブクイックスタート• Android ネイティブクイックスタート

11

クイックスタートSalesforce Mobile SDK 開発の概要

第 3 章 Mobile SDK 4.3 の新機能

Mobile SDK 4.3 では、SmartStore への重要な変更といくつかのサードパーティコンポーネントの更新が行われています。

アプリケーションのアップグレード方法

既存の Mobile SDK アプリケーションをアップグレードするには、「以前のリリースからの移行」の手順に従います。

Mobile SDK 4.3 の SmartStore の新機能• Android のみ、SmartStoreの SQLCipherがバージョン 3.5.2 (2016 年 7 月)にアップグレー

ドされています。iOS の場合、SmartStore の SQLCipher は 3.4.0 (2016 年 4 月) のままです。

• 特定の極端な状況でパフォーマンスを向上させるため、外部ストレージの非常に大きいスープ要素を逐次化するオプションが SmartStore に追加されました。「大きいスープ要素での外部ストレージの使用」を参照してください。

Mobile SDK 4.3 のハイブリッドアプリケーションの新機能• Mobile SDK 4.3 の Cordova サポートが次のようにアップグレードされています。

– iOS: Cordova 4.2.0 にアップグレード– Android: 変更なし — Cordova 5.0.0 のまま

Mobile SDK 4.3 の React Native の新機能• バージョンの更新 — Mobile SDKは、React Nativeバージョン 0.30.0で構築されるよう

になりました。

12

第 4 章 最近のリリースの新機能

次に、最近の Mobile SDK リリースの新機能のお知らせのアーカイブを示します。

Mobile SDK 4.2 の SmartStore の新機能

Mobile SDK 4.2 では、SmartStore の基盤となるテクノロジが SQLite バージョン 3.11.0 (2016

年 2 月) と SQLCipher バージョン 3.4.0 (2016 4 月) にアップグレードされています。そのため、SmartStore で JSON1 インデックスとアップグレードされた全文検索エンジン(FTS5) を利用できるようになりました。SmartStore の改善内容は次のとおりです。• JSON1 インデックス指定の型 — 「SmartStore のデータ型」を参照してください。• FTS5 — Mobile SDK の全文検索モジュールが FTS5 にアップグレードされました。

「全文検索による最新情報の把握」を参照してください。• 新しいデフォルトインデックス — _soupLastModifiedDate および

_soupCreatedDateシステム項目にデフォルトインデックスが追加されました。「システム項目のインデックス」を参照してください。

• クエリによる削除 — スープ要素を ID のリストではなくクエリで削除できるようになりました。「スープ要素の削除」を参照してください。

• 返される項目の制限 — 指定した項目のリストが返されるようにクエリ指定のタイプを設定します。「項目のサブセットを返すクエリの絞り込み」を参照してください。

Mobile SDK 4.2 の SmartSync の新機能

SmartSync では、「ゴースト」スープ要素を削除するメソッドが提供されるようになりました。ゴースト要素は、サーバで削除された後や下位同期クエリに一致しなくなった後にスープに残るスープエントリです。「下位同期操作後の「ゴースト」レコードの処理」を参照してください。

Mobile SDK 4.2 の React Native の新機能• バージョンの更新 — Mobile SDKは、React Nativeバージョン 0.27.2 で構築されるよう

になりました。• 遅延ログイン — 任意の場所に Salesforce ログインプロンプトを配置できるように

なりました。配置方法は、ターゲットプラットフォームによって異なります。「ログインの延期」を参照してください。

13

• バイナリアップロード — バイナリアップロードがサポートされる Salesforce エンドポイントにバイナリコンテンツをアップロードできます。「バイナリコンテンツのアップロード」を参照してください。

• SmartStore の機能強化 — SmartStore の新機能と改善された機能については、「SmartStore」の章を参照してください。React Nativeでは、更新されたメソッド署名に見られるような並列機能が提供されます。

Mobile SDK 4.2 のその他の変更および更新• Instant Run (Android のみ) — Mobile SDKで Android Studio の Instant Run 機能がサポート

されるようになりました。• OkHttp (Android のみ) — Google Volley ネットワーキングライブラリが OkHttp に置き

換えられました。「OkHttp: 基盤となるネットワークライブラリ」を参照してください。

• [設定] アイコンの非表示 (iOS のみ) — ユーザがログインサーバを変更できないように、ログイン画面の [設定] アイコンをプログラムで非表示にできます。「iOS

アプリケーションでの設定アイコンの非表示」を参照してください。• SQLCipher のアップグレード — SQLCipher モジュールがバージョン 3.4 にアップグ

レードされました。

Mobile SDK 4.1 の概要

サンプルの改善とバグの修正に加えて、Mobile SDK 4.1 では、次のような更新が行われています。• SmartStore で、インデックスパスに内部 (非リーフ) ノードを使用できるようにな

りました。この機能は、LIKE および MATCH クエリで便利です。• SmartStore で、複合インデックスパスに配列を使用できるようになりました。• React Native がバージョン 0.20.0 に更新されました。• —iOS の設定バンドルが削除されました。ユーザが [設定] を使用してログアウト

する場合、独自のログアウトボタンを実装してこの機能を復元できます。• iOS でカスタムログインホストを設定するときに [設定] が使用されなくなりまし

た。代わりに、ログイン画面から実行時にカスタムログインホストを追加できます。

Mobile SDK 4.1 のドキュメントの更新

Mobile SDK 4.1 では、次のトピックが更新されました。• スープの登録• インデックスパスでの配列の使用• Android アプリケーションでのカスタムログインサーバの設定

14

最近のリリースの新機能

Mobile SDK 4.0 の概要

モバイル開発は、過去数年で急速に発展しました。CocoaPods、Gradle、および NuGet

などのツールの登場により、連動関係の管理および作成の自動化が簡略化されました。Swift 言語および React Native フレームワークが人気のコーディングオプションになりました。最新のベストプラクティスに準拠するために、Salesforce Mobile SDK 4.0 では、これらのテクノロジをそのワークフローに緊密に統合します。旧世代のMobile SDKで作成されたアプリケーションは、Mobile SDK 4.0 にアップグレードすることで大きな利点を得られます。アップグレードを簡単に行うには、新しいバージョンの forceios または forcedroid を使用してプロジェクトを作成し、既存のコードをそのプロジェクトに移行します。古いコードに影響するアーキテクチャの変更、廃止、およびベストプラクティスについては、「以前のリリースからの移行」を参照してください。

Mobile SDK 4.0 のドキュメントの更新

Mobile SDK 4.0 の新しいドキュメントや変更されたドキュメントは、次のとおりです。• Salesforce Mobile SDK の React Native

• Salesforce Mobile SDK アプリケーションでの MDM の使用• ネイティブ iOS の要件• forceios を使用した iOS プロジェクトの作成• CocoaPods と Mobile SDK の使用• SalesforceSDKManager および SmartStoreSDKManager クラス• ネイティブ Android の要件• Android プロジェクトの作成• Mobile SDK Labs へようこそ

その他の新機能のリスト

Mobile SDKの最新リリースの新機能のリストは、次の場所でいつでも確認できます。• GitHub の Android Readme

• GitHub の iOS Readme

15

最近のリリースの新機能

第 5 章 Mobile SDK 4.3 for Android および iOS の使用開始

カスタムモバイルアプリケーションを作成してみましょう。まだ Force.com にサインアップして Mobile SDK 開発ツールをインストールしていない場合は、まずこのサインアップとインストールを実行します。

トピック:

• Developer Edition 環境か Sandbox 環境か どの開発オプションを選択する場合でも、サインアップすることに加え、接続アプ

リケーションを定義する必要があります。Mobile SDK for Android または iOS (ハイブリッ• Android および iOSの開発の前提条件 ドおよびネイティブ) をインストールするには、Mobile SDK npm パッケージを使用し

ます。• Force.com のサインアップ

• 接続アプリケーションの作成

• Mobile SDK forAndroid および iOSのインストール

• Mobile SDK サンプルアプリケーション

16

Developer Edition 環境か Sandbox 環境か

Salesforceでは、開発者向けにさまざまな環境を提供しています。最適な環境は、次のような多くの要因によって開発者ごとに異なります。• 作成しているアプリケーションのタイプ• アプリケーションの利用者• 会社のリソース開発環境の使用目的は、アプリケーションの開発およびテストに限定されています。この環境には、ビジネスに不可欠ではないテストデータが含まれます。開発は、ブラウザ内で行うことも、Eclipse 開発ツールに基づいた Force.com IDE を使用して行うこともできます。

開発者環境の種別Developer Edition環境は、無料で利用できる全機能が搭載された Enterprise Edition 環境のコピーで、ストレージ容量とユーザ数に制限があります。Developer Edition は論理的に独立した環境で、最初の開発環境として理想的です。必要な数の Developer Edition 組織にサインアップできます。そのため、どの Salesforce 本番環境向けに設計されたアプリケーションでも作成できます。Partner Developer Editionは、無料で利用できる Developer Edition のライセンスバージョンで、より多くのストレージ容量、機能、ライセンスが含まれます。Partner Developer Edition は、登録済みの Salesforce パートナーに無料で提供されます。Sandbox は本番環境とほぼ一致するコピーであり、Professional Edition、Enterprise Edition、Performance Edition、および Unlimited Edition の顧客が使用できます。Sandbox コピーには、データ、設定、またはその両方を含めることができます。さまざまな目的のために、本番環境のデータとアプリケーションに影響を与えることなく、複数の Sandbox を本番環境で作成できます。

環境の選択このガイドでは、すべての練習で Developer Edition 組織を使用することを想定しています。ただし、実際にはSandbox 環境でも開発作業を行うことができます。次に、最適な環境の決定に役立つ情報を示します。• Developer Edition が最適なユーザ

– 商用 Force.com アプリケーションの構築を目的に、AppExchange や Trialforce で配布する管理パッケージを作成するパートナー。管理パッケージを作成できるのは、Developer Edition 環境または Partner Developer Edition

環境のみです。– Sandbox へのアクセス権のない、Group Edition または Personal Edition の Salesforce 顧客。– Force.com プラットフォームを無料で検証しようとする開発者。

• Partner Developer Edition が最適な場合– すべてのソースコードを管理するマスタ環境を必要とする開発チームが利用する。この場合、開発者ご

とに Developer Edition 環境を設定し、このマスタリポジトリ環境との間でコードをチェックインおよびチェックアウトできます。

– 開発とテストのために 3 人以上の開発者がログインする可能性がある。

17

Developer Edition 環境か Sandbox 環境かMobile SDK 4.3 for Android および iOS の使用開始

– 大量のデータセットに対して多くのユーザがロバストテストを実行できる大規模な環境を必要とする。• Sandbox が最適な場合

– Sandbox が含まれる Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、または Force.com

Edition の Salesforce ユーザである。– 本番環境用の Force.com アプリケーションを開発している。– 市販される Force.com アプリケーションを作成する予定がない。– AppExchange に載せたり、Trialforce を使用して配布したりする意図がない。

Android および iOS の開発の前提条件

ある程度の予備知識の習得やシステム設定を経験してから Mobile SDK アプリケーションの作成を始めることをお勧めします。Force.com に関するある程度の経験があると役立ちます。Force.com Developer Edition 組織も必要です。Mobile SDKアプリケーションの設計やデバッグを行うには、OAuth、ログインおよびパスコードフロー、Salesforce

接続アプリケーションについて熟知している必要があります。「モバイルアプリケーションでの認証、セキュリティ、ID」を参照してください。次の要件は、特定のプラットフォームおよびテクノロジに適用されます。

iOS の要件• iOS 8 以降。• Xcode — バージョン 7 以降 (最新バージョンを推奨)。• CocoaPods (cocoapods.org)。• forceios、バージョン 4.3。• 接続アプリケーションが存在する Salesforce Developer Edition 組織。

Android の要件• Java JDK 7 以降 — www.oracle.com/downloads。• Node Package Manager (npm) — SalesforceMobileSDK-Android リポジトリへの直接アクセスを含む、すべての

Android 開発シナリオでインストールする必要があります。• Android Studio 2 以降 — developer.android.com/sdk。• Android SDK および Android SDK Tools — Android Studio 内からインストールします。

1. Android Studio メニューで、[ツール] > [Android] > [SDK Manager] をクリックします。2. [SDK Platforms] タブをクリックします。3. 少なくとも次の必須 SDK レベルとすべての中間レベルをインストールします。

– 最小限の API: Android KitKat (API 19)

– 対象の API: Android Marshmallow (API 23)

18

Android および iOS の開発の前提条件Mobile SDK 4.3 for Android および iOS の使用開始

4. [SDK Tools] タブをクリックします。5. 最新バージョンの Android SDK Tools をインストールします。

• Android 仮想デバイス (AVD) — Android Studio 内からインストールします。1. Android Studio メニューで、[ツール] > [Android] > [AVD マネージャ] をクリックします。2. [仮想デバイスを作成...] をクリックします。3. Android KitKat (API 19) 以上を対象とする AVD を少なくとも 1 つインストールします。Android Studio で AVD を

設定する方法については、developer.android.com/guide/developing/devices/managing-avds.html の手順を参照してください。

ハイブリッドの要件• サポートする各モバイルプラットフォームのすべての要件 (前述のセクションを参照)。• HTML5 および JavaScript 言語に習熟している。• ハイブリッドリモートアプリケーションの場合:

– Visualforce のある Salesforce 組織。– Visualforce の開始ページ。

Force.com のサインアップ

すべてのSalesforce開発者プログラムの豊富なチュートリアル、ブログ、およびサポートフォーラムにアクセスするには、Force.com に参加します。1. ブラウザで https://developer.salesforce.com/signupにアクセスします。2. 各項目にユーザ情報と会社情報を入力します。3. [Email Address (メールアドレス)] 項目には、Web ブラウザから簡単に確認できる公開アドレスを使用

してください。4. 一意の [Username (ユーザ名)] を入力します。ユーザ名もメールアドレスの形式にする必要があります

が、メールアドレスと同じにする必要はなく、通常は違うものを入力することをお勧めします。ユーザ名は developer.salesforce.comでのログイン情報および ID であるため、担当する作業を説明するユーザ名 ([email protected]) や自分自身を表すユーザ名 ([email protected]) を選ぶことで、より有益に使用できます。

5. [Master Subscription Agreement (マスターサブスクリプション契約)] を読み、チェックボックスをオンにします。

6. 表示された画像認証文字列を入力し、[Submit Registration (登録を実行)] をクリックします。7. その後まもなく、ログインリンクを記載したメールが届きます。リンクをクリックし、パスワードを変更

します。

19

Force.com のサインアップMobile SDK 4.3 for Android および iOS の使用開始

接続アプリケーションの作成

モバイルアプリケーションからSalesforceサービスに接続できるようにするには、接続アプリケーションを作成する必要があります。接続アプリケーションには、このガイドのすべての開発シナリオの前提条件となるコンシューマ鍵が含まれます。

接続アプリケーションを作成する接続アプリケーションを作成するには、Salesforce アプリケーションを使用します。1. Force.com インスタンスにログインします。2. [設定] から、[クイック検索]ボックスに「アプリケーション」と入力し、[アプリケーション]を選択します。3. [接続アプリケーション] で、[新規] をクリックします。4. 「基本情報」の手順を実行します。5. 「API (OAuth 設定の有効化)」の手順を実行します。6. [保存] をクリックします。転送通知をサポートする予定の場合、追加の接続アプリケーション設定については、「転送通知と Mobile SDK」を参照してください。現在必要な情報がない場合は、後でこれらの設定を追加できます。

メモ:

• OAuth 用に提供される [コールバック URL] は、有効な URL である必要はありません。必要なのは、アプリケーションでこの項目に期待する内容と一致していることだけです。「sfdc://」など、任意のカスタムプレフィックスを使用できます。

• 接続アプリケーションの詳細ページに、コンシューマ鍵が表示されます。このキーは後で必要になるため、コピーしておくことをお勧めします。

• 新しい接続アプリケーションを作成したら、トークンが伝搬されるまで数分待ってから、アプリケーションを実行します。

基本情報このセクションでは、アプリケーション名、ロゴ、連絡先情報など、アプリケーションに関する基本情報を指定します。1. [接続アプリケーション名] を入力します。この名前が接続アプリケーションのリストに表示されます。

メモ: 現在の接続アプリケーションの名前は、組織内で一意にする必要があります。接続アプリケーションが Spring '14 以降のリリースを使用して作成された場合は、削除済み接続アプリケーションの名前を再使用できるようになりました。接続アプリケーションが Spring '14 より前のリリースを使用して作成された場合は、削除済み接続アプリケーションの名前は再使用できません。

2. プログラムからアプリケーションを参照するときに使用する [API 参照名] を入力します。API 参照名は、デフォルトの空白を除いた名前になります。使用できるのは、文字、数字、アンダースコアのみであるため、元のアプリケーション名に他の記号などが含まれている場合は、デフォルトの名前を編集する必要があります。

20

接続アプリケーションの作成Mobile SDK 4.3 for Android および iOS の使用開始

3. Salesforce からアプリケーション提供者またはそのサポートチームへの連絡に使用する [取引先責任者 メール] を入力します。このアドレスは、アプリケーションをインストールするシステム管理者には提供されません。

4. Salesforce から連絡する必要がある場合に使用する [取引先責任者 電話] を入力します。この番号は、アプリケーションをインストールするシステム管理者には提供されません。

5. 接続アプリケーションのリストや、認証時にユーザに表示される同意ページにロゴを表示するには、[ロゴ画像 URL] を入力します。URL には HTTPS を使用する必要があります。ロゴは、高さ 125 ピクセル以下、幅200 ピクセル以下、ファイルサイズ 100 KB 以下の GIF、JPG、または PNG ファイル形式にする必要があります。デフォルトは雲のロゴです。カスタムロゴを追加するには複数の方法があります。• [ロゴ画像をアップロード]をクリックして、独自のロゴ画像をアップロードできます。ローカルファイ

ルシステムからロゴのサイズ要件を満たす画像を選択します。アップロードが成功すると、ロゴへのURL が [ロゴ画像 URL] 項目に表示されます。表示されない場合は、ロゴのサイズ要件を満たしていることを確認します。

• [いずれかのサンプルロゴを選択]をクリックして、提供されているサンプルからロゴを選択することもできます。Salesforceアプリケーション、サードパーティアプリケーション、標準化団体のロゴなどを使用できます。目的のロゴをクリックし、表示される URL をコピーして [ロゴ画像 URL] 項目に貼り付けます。

• Salesforce サーバで公開されてホストされるロゴを使用できます。これを行うには、[ドキュメント] タブを使用して、ロゴファイル要件 (高さ 125 ピクセル以下、幅 200 ピクセル以下、ファイルサイズ 100 KB 以下の GIF、JPG、または PNG ファイル形式) を満たす画像をドキュメントとしてアップロードします。次に、画像を表示して URL を取得し、その URL を [ロゴ画像 URL] 項目に入力します。

6. ユーザがアプリケーションを初めて使用するときに表示される OAuth 承認ページにロゴを表示するには、[アイコン URL]を入力します。ロゴは、16×16 ピクセル (高さ×幅) で、背景色は白にします。サンプルロゴはアイコンにも使用できます。[いずれかのサンプルロゴを選択]をクリックして、提供されているサンプルからアイコンを選択できます。目的のアイコンをクリックし、表示される URL をコピーして [アイコン URL] 項目に貼り付けます。

7. アプリケーションについての詳細が記載された Web ページがある場合、[情報 URL] を入力します。8. 接続アプリケーションのリストに表示される [説明] を入力します。Winter '14 より前では、[開始 URL] と [モバイル開始 URL] はこのセクションで定義されていました。現在、これらの項目は、以下の [Web アプリケーション設定] および [モバイルアプリケーション設定] にあります。

API (OAuth 設定の有効化)このセクションでは、アプリケーションがSalesforceと通信する方法を管理します。認証設定を定義するには、[OAuth 設定の有効化] を選択します。1. Salesforce が OAuth 時にアプリケーションにコールバックする [コールバック URL] (エンドポイント) を入力

します。これは、OAuth redirect_uriです。使用する OAuth フローに応じて、これは通常、認証が成功した後にユーザのブラウザがリダイレクトされる URL になります。この URL は一部の OAuth フローでアクセストークンを渡すために使用されるため、URL はセキュア HTTP (HTTPS) またはカスタム URI スキームを使用する必要があります。複数のコールバック URL を入力すると、[コールバック URL] のいずれかの値を使用して

21

接続アプリケーションを作成するMobile SDK 4.3 for Android および iOS の使用開始

アプリケーションで指定されたコールバック URL の値が、Salesforce により実行時に照合されます。検証テストに通過するには、いずれか 1 つの値と一致する必要があります。

2. JWT OAuth フローを使用している場合は、[デジタル署名を使用] を選択します。アプリケーションが証明書を使用する場合は、[ファイルを選択] をクリックして、証明書のファイルを選択します。

3. サポートされているすべての OAuth 範囲を [選択した OAuth 範囲] に追加します。これらの範囲は、接続アプリケーションを実行するユーザによって付与される権限を示し、その後に続く括弧内には OAuth トークン名が表示されます。Chatter フィードへのアクセスと管理 (chatter_api)

Chatter REST API リソースへのアクセスのみを許可します。データへのアクセスと管理 (api)

REST API や Bulk API などの API を使用したログインユーザの取引先へのアクセスを許可します。この値には、Chatter REST API リソースへのアクセスを許可する chatter_api も含まれます。

基本情報へのアクセス (id、profile、email、address、phone)

ID URL サービスへのアクセスを許可します。カスタム権限へのアクセス (custom_permissions)

接続アプリケーションに関連付けられている組織のカスタム権限へのアクセスを許可し、現在のユーザで各権限が有効かどうかを示します。

一意の識別子へのアクセスを許可 (openid)

ログインユーザの OpenID Connect アプリケーションの一意の識別子へのアクセスを許可します。フルアクセス (full)

ログインユーザがアクセスできるすべてのデータへのアクセスを許可し、その他すべての範囲が対象となります。full は更新トークンを返しません。更新トークンを取得するには、refresh_token の範囲を明示的に要求する必要があります。

ユーザに代わっていつでも要求を実行 (refresh_token、offline_access)

更新トークンを受信できる場合に、それを返すように指定します。これにより、ユーザがオフラインのときにアプリケーションがユーザのデータを操作できます。refresh_token範囲は、offline_access

と同じです。カスタムアプリケーションへのアクセスの提供 (visualforce)

Visualforce ページへのアクセスを許可します。Web 経由のデータへのアクセスを提供 (web)

Web で access_tokenを使用することを許可します。これには visualforceも含まれ、Visualforceページへのアクセスが許可されます。

4. OAuth 要求で ID トークンを処理する方法を制御します。OAuth 要求に openid 範囲が含まれる場合、返されるトークンに ID トークンが含まれる可能性があります。• 更新トークン応答に ID トークンを含めるには、[ID トークンを含める] を選択します。ID トークンはア

クセストークン応答に常に含まれます。• プライマリ ID トークン設定を有効にした状態で、アクセストークン応答と更新トークン応答の両方で

ID トークンコンテンツを制御するセカンダリ設定を構成します。少なくとも 1 つの設定を選択します。

22

接続アプリケーションを作成するMobile SDK 4.3 for Android および iOS の使用開始

標準要求を含めるユーザの名前、プロファイル、電話番号、住所など、ユーザに関する情報を含む標準要求を含めます。「OpenID Connect の仕様」では、ID トークンで返される、一連の標準要求が定義されます。

カスタム属性を含めるアプリケーションでカスタム属性を指定した場合は、そのカスタム属性を ID トークンに含めます。

カスタム権限を含めるアプリケーションでカスタム権限を指定した場合は、そのカスタム権限を ID トークンに含めます。

Spring '12 リリースより前に、組織でリモートアクセスに対して [この組織のユーザにはユーザ承認は必要ありません]オプションが選択されていた場合、アプリケーションが作成された組織と同じ組織のユーザは、引き続きアプリケーションで自動的に承認されます。参照のみの [この組織のユーザにはユーザ承認は必要ありません]チェックボックスがオンで表示されている場合は、この状態であることを示します。接続アプリケーションの場合、アプリケーションを作成したら、システム管理者がアプリケーションをインストールし、[許可されているユーザ] を [管理者が承認したユーザ] に設定することをお勧めします。当初リモートアクセスオプションがオフだった場合、チェックボックスは表示されません。

関連トピック:

範囲パラメータの値

Mobile SDK for Android および iOS のインストール

Salesforce Mobile SDK には、2 つのインストールパスがあります。• (推奨) Node Packaged Module (npm) スクリプトを使用して、用意された開発設定に SDK をインストールできま

す。• Mobile SDK オープンソースコードを GitHub からダウンロードし、独自の開発環境を設定できます。

Mobile SDK npm パッケージモバイル開発者のほとんどは、Mobile SDK を「ブラックボックス」として使用することで、できるだけ早くアプリケーションの作成を開始することができます。そのため、Salesforceには、iOS 用の forceiosと、Android 用のforcedroid という 2 つの npm パッケージが用意されています。Mobile SDK npm パッケージには、SDK リリースの静的スナップショットが含まれています。iOS の npm パッケージでは、未コンパイルのソースコードではなくバイナリモジュールがインストールされます。Android の npm

パッケージでは、バイナリではなく SDK ソースコードのスナップショットがインストールされます。npm スクリプトでは、Mobile SDK をインストールするだけでなく、テンプレートプロジェクトも作成します。Salesforce Mobile SDK 用の npm パッケージは、https://www.npmjs.org にあります。

メモ: npm パッケージではソース制御がサポートされないため、新しいリリース用にインストールを動的に更新することはできません。代わりに、リリースごとに別個にインストールします。新しいバージョンの SDK にアップグレードするには、npmjs.orgの Web サイトにアクセスして、新しいパッケージをダウンロードしてください。

23

Mobile SDK for Android および iOS のインストールMobile SDK 4.3 for Android および iOS の使用開始

最初の作業: Node.js および npm をインストールするMobile SDK npm インストーラを使用するには、まず Node.js をインストールします。Node.js インストーラにより、npm が自動的にインストールされます。1. www.nodejs.org から Node.js をダウンロードします。2. Node.js および npm をインストールするには、ダウンロードしたインストーラを実行します。インストール

の許可を求めるプロンプトをすべて承諾します。3. コマンドプロンプトで「npm」と入力して Enter または Return キーを押し、インストールをテストしま

す。コマンドの使用状況情報のページが表示されない場合、ステップ 2 に戻り、何が欠落しているのかを調べます。

これで、npm スクリプトをダウンロードして、Salesforce Mobile SDK for Android および iOS をインストールできるようになりました。

iOS のインストール最も迅速で簡単に iOS 開発をはじめるには、forceios npm パッケージを使用して Salesforce Mobile SDKをインストールしてください。Mobile SDK 4.0 以降では、forceios に CocoaPods が必要になります。forceios で作成されたアプリケーションは、CocoaPod 駆動型ワークスペースで実行されます。CocoaPods ユーティリティでは、Mobile SDKソースコードをワークスペースで使用できるようにしてデバッグを強化します。また、CocoaPods を使用すれば、新しい Mobile SDK

バージョンに簡単に更新できます。プロファイルを更新して、ターミナルウィンドウで pod update を実行するだけで済みます。1. guides.cocoapods.org の「Getting Started」の手順を使用して CocoaPods をインストールします。2. forceios npm パッケージをインストールします。ターミナルウィンドウを開いて、「sudo npm install

forceios -g」と入力します。「グローバル」パラメータ (-g) を使用すると、forceios を任意のディレクトリから実行できます。npm ユーティリティにより forceios パッケージが /usr/local/lib/node_modules にインストールされ、/usr/local/bin のバイナリモジュールにリンクされます。大部分のユーザは /usr/local の「参照・更新」権限がないため、sudo が必要になります。

Android のインストール最も迅速で簡単に Android 開発をはじめるには、forcedroid npm パッケージをインストールして Android 用のSalesforce Mobile SDK プロジェクトを作成してください。• Mac OS X (または他の非 Windows 環境) — ターミナルウィンドウに次のコマンドを入力します。

sudo npm install forcedroid -g

npm ユーティリティによって /usr/local/lib/node_modules にパッケージがインストールされ、/usr/local/binのバイナリモジュールがリンクされます。/usr/localの「参照・更新」権限がない場合、sudo コマンドが必要になります。

24

Mobile SDK npm パッケージMobile SDK 4.3 for Android および iOS の使用開始

• Windows — Windows コマンドプロンプトに次のコマンドを入力します。npm install forcedroid -g

npm ユーティリティによって %APPDATA%\npm\node_modules にパッケージがインストールされ、%APPDATA%\npm のバイナリがリンクされます。

メモ: npm の -g パラメータを使用すると、forcedroid を任意のディレクトリからコールできるようになります。

Mobile SDK npm パッケージのアンインストールnpm パッケージをアンインストールする必要がある場合は、npm スクリプトを使用します。

forcedroid パッケージのアンインストールforcedroid パッケージのアンインストール手順は、パッケージをグローバルにインストールしたか、ローカルにインストールしたかによって異なります。パッケージをグローバルにインストールした場合、任意のフォルダから uninstall コマンドを実行できます。–g オプションを必ず使用してください。Mac OS X などの Unix ベースのプラットフォームの場合は、sudo

を使用してください。$ pwd/Users/joeuser$ sudo npm uninstall forcedroid -g$

パッケージをローカルにインストールした場合、パッケージをインストールしたフォルダから uninstallコマンドを実行します。次に例を示します。cd <my_projects/my_sdk_folder>npm uninstall forcedroid

誤ったディレクトリからローカルインストールをアンインストールしようとすると、次のようなエラーメッセージが表示されます。npm WARN uninstall not installed in /Users/joeuser/node_modules:"my_projects/my_sdk_folder/node_modules/forcedroid"

forceios パッケージのアンインストールforceios パッケージのアンインストール手順は、パッケージをグローバルまたはローカルのどちらでインストールしたかによって異なります。パッケージをグローバルにインストールした場合、任意のフォルダからuninstall コマンドを実行できます。sudo および –g オプションを必ず使用してください。$ pwd/Users/joeuser$ sudo npm uninstall forceios -g$

25

Mobile SDK npm パッケージMobile SDK 4.3 for Android および iOS の使用開始

ローカルでインストールしたパッケージをアンインストールするには、パッケージをインストールしたフォルダから uninstall コマンドを実行します。次に例を示します。$ pwd/Users/joeusercd <my_projects/my_sdk_folder>npm uninstall forceios

誤ったディレクトリからローカルインストールをアンインストールしようとすると、次のようなエラーメッセージが表示されます。npm WARN uninstall not installed in /Users/joeuser/node_modules:"my_projects/my_sdk_folder/node_modules/forceios"

Mobile SDK GitHub リポジトリ開発者は、GitHub で SDK を探求して、変更を最新に保ち、さらに SDK 開発に貢献するなどを積極的に行うことができます。GitHub を使用すれば、公開されたプレリリースの開発環境でソースコードを監視できます。この場合、アプリケーションと共に構築される SDK ソースコードがアプリケーションに含まれます。Mobile SDK にアクセスするために GitHub にサインアップする必要はありませんが、このソーシャルコーディングコミュニティに参加することをお勧めします。https://github.com/forcedotcom

最新の Mobile SDK リリースは、次の公開リポジトリからいつでも入手できます。• https://github.com/forcedotcom/SalesforceMobileSDK-iOS

• https://github.com/forcedotcom/SalesforceMobileSDK-Android

重要: Mobile SDK プラットフォームのプル要求を送信するには、変更のベースとして unstable ブランチをチェックアウトします。GitHub を使用して最新リリースのソースコードの作成のみを行う場合、master ブランチをチェックアウトします。

Mobile SDK for iOS GitHub リポジトリのコピー (省略可能)1. OS X ターミナルアプリケーションで git clone

git://github.com/forcedotcom/SalesforceMobileSDK-iOS.git コマンドを発行して、Mobile SDK

for iOS リポジトリをローカルファイルシステムにコピーします。

メモ: Mac OS X 用の GitHub アプリケーションの場合は、[Clone in Mac (Mac でクローン)] をクリックします。ブラウザで、Mobile SDK iOS GitHub リポジトリ(https://github.com/forcedotcom/SalesforceMobileSDK-iOS) に移動します。

2. OS X ターミナルアプリケーションで、コピーしたリポジトリをインストールしたディレクトリ (デフォルトでは SalesforceMobileSDK-iOS) にこれを変更します。

3. コマンドラインからインストールスクリプト ./install.sh を実行します。

26

Mobile SDK GitHub リポジトリMobile SDK 4.3 for Android および iOS の使用開始

Mobile SDK for Android GitHub リポジトリのコピー (省略可能)1. ブラウザで、Mobile SDK for Android GitHub リポジトリ https://github.com/forcedotcom/SalesforceMobileSDK-Android に

移動します。2. git clone git://github.com/forcedotcom/SalesforceMobileSDK-Android.git コマンドを使用

して、リポジトリをローカルファイルシステムにコピーします。3. コピーしたリポジトリをインストールしたディレクトリで、ターミナルプロンプトまたはコマンドウィン

ドウを開きます。4. ./install.sh (Mac) または cscript install.vbs (Windows) を実行します。

メモ: Windows で cscript install.vbs を実行すると、git status により、変更されたファイルおよび削除されたファイルのリストが返されます。この出力は、リポジトリのシンボリックリンクの解決の好ましくない副作用です。これらのファイルは、クリーンアップしたり、元に戻したりしないでください。

コピーされた GitHub リポジトリを使用した Android プロジェクトの作成コピーされた SalesforceMobileSDK-Android リポジトリを使用してネイティブおよびハイブリッドプロジェクトを作成するには、native/README.md および hybrid/README.md ファイルの手順に従います。

メモ: 必ず Mobile SDK for Android を作成する前に npm をインストールしてください。

コピーされた GitHub リポジトリを使用した iOS プロジェクトの作成コピーされた SalesforceMobileSDK-iOSリポジトリを使用してプロジェクトを作成するには、リポジトリのルートディレクトリにある build.md の手順に従います。

関連トピック:

最初の作業: Node.js および npm をインストールする

Mobile SDK サンプルアプリケーション

Salesforce Mobile SDK には、主要な機能を示す豊富なサンプルアプリケーションが含まれています。ハイブリッドサンプルとネイティブサンプルは、独自のアプリケーションの基盤として使用したり、参考のために検討したりできます。

サンプルアプリケーションのインストールGitHub では、サンプルアプリケーションは対象プラットフォームの Mobile SDK リポジトリに存在します。ハイブリッドサンプルでは、Cordova コマンドラインで SalesforceMobileSDK-Shared リポジトリのソースコードを使用できます。

27

Mobile SDK サンプルアプリケーションMobile SDK 4.3 for Android および iOS の使用開始

GitHub リポジトリからサンプルアプリケーションへのアクセスMobile SDK を GitHub から直接コピーすると、サンプルファイルが hybrid/HybridSampleApps およびnative/NativeSampleApps ディレクトリに配置されます。Android の場合: ローカルでのリポジトリのコピーまたは更新後に、リポジトリルートフォルダにある Windows

の cscript install.vbs または Mac の ./install.sh を実行します。その後 SalesforceMobileSDK-Android プロジェクトを Android Studio にインポートして、Android のサンプルを作成できます。hybrid/HybridNativeSamples および native/NativeHybridSamples プロジェクトフォルダでサンプルアプリケーションを探します。

重要: Windows では、必ずシステム管理者として Android Studio を実行します。

iOS の場合:ローカルでのリポジトリのコピーまたは更新後に、リポジトリルートフォルダにある ./install.sh

を実行します。その後 Xcode で SalesforceMobileSDK-iOS/SalesforceMobileSDK.xcworkspace ファイルを開き、iOS のサンプルを作成できます。NativeSamples および HybridSamples ワークスペースフォルダでサンプルアプリケーションを探します。

Cordova でのハイブリッドサンプルアプリケーションの作成Cordova コマンドラインを使用してハイブリッドサンプルアプリケーションを作成するには、「ハイブリッドサンプルアプリケーションを作成する」を参照してください。

Android サンプルアプリケーション

ネイティブ• RestExplorer: Mobile SDKの OAuth および REST API 機能を示します。また、REST API アクションをタブレットから

調べる場合にも便利です。• SmartSyncExplorer: Android 上でのネイティブ SmartSync ライブラリの機能を示します。これは、

native/NativeSampleApps/SmartSyncExplorer の Mobile SDK for Android にあります。

ハイブリッド• AccountEditor: smartsync.js ライブラリを使用してオフラインデータを同期する方法について説明しま

す。• NoteSync: 非 REST API を使用して Salesforce のメモを取得する方法を示します。• SmartSyncExplorerHybrid: SmartSync プラグインを使用してオフラインデータを同期する方法について説明し

ます。

28

サンプルアプリケーションのインストールMobile SDK 4.3 for Android および iOS の使用開始

iOS サンプルアプリケーション

ネイティブ• RestAPIExplorer では、ネイティブのすべての REST API ラッパーが実行されます。これは、

native/SampleApps/RestAPIExplorer の Mobile SDK for iOS にあります。• SmartSyncExplorer には、iOS 上でのネイティブ SmartSync ライブラリの機能が示されます。これは、

native/SampleApps/SmartSyncExplorer の Mobile SDK for iOS にあります。

ハイブリッド• AccountEditor: smartsync.js ライブラリを使用してオフラインデータを同期する方法について説明しま

す。• NoteSync: 非 REST API を使用して Salesforce のメモを取得する方法を示します。• SmartSyncExplorerHybrid: SmartSync プラグインを使用してオフラインデータを同期する方法について説明し

ます。

ハイブリッドサンプルアプリケーション (ソースのみ)Mobile SDK では、ほとんどのハイブリッドサンプルアプリケーションの Web アプリケーションソースコードのみが提供されています。Cordova コマンドラインを使用して、これらのアプリケーションのプラットフォーム固有のバージョンを作成できます。ソースコードを入手するには、SalesforceMobileSDK-Shared GitHub リポジトリをコピーし、samples フォルダを確認します。特定のモバイルプラットフォーム用にこれらのハイブリッドアプリケーションを作成する場合は、「ハイブリッドサンプルアプリケーションを作成する」の説明を参照してください。• accounteditor: SmartSync Data Framework を使用して Salesforce データにアクセスします。• contactexplorer: Cordova を使用してローカルデバイスの取引先責任者を取得します。また、

forcetk.mobilesdk.js ツールキットを使用して、Salesforce REST API で REST トランザクションを実装します。アプリケーションでは、Salesforce SDK の OAuth2 サポートを使用して OAuth ログイン情報を取得し、JavasScript イベントを送信することによって、そのログイン情報を forcetk.mobilesdk.js に伝搬します。

• fileexplorer: Files API を示します。• notesync: 非 REST API を使用して Salesforce のメモを取得します。• simplesyncreact:: SmartSync プラグインを使用する React Native アプリケーションのデモを実施します。• smartstoreexplorer: SmartStore API を探索できます。• smartsyncexplorer: SmartSyncプラグインではなく smartsync.jsを使用してオフライン同期を行うデモを実

施します。• userandgroupsearch: グループのユーザを検索できます。• userlist: 組織のユーザをリストします。これは、最も単純なハイブリッドサンプルアプリケーションです。• usersearch: 組織のユーザを検索できます。• vfconnector: ネイティブコンテナ内の Visualforce ページをラップします。この例では、BasicVFTest という

Visualforceページが組織に存在することを想定しています。アプリケーションではまず、Salesforce SDK OAuth2

29

サンプルアプリケーションのインストールMobile SDK 4.3 for Android および iOS の使用開始

サポートを使用して OAuth のログイン情報を取得し、そのログイン情報を使用して、Visualforce ページにアクセスするための適切な Web ビュー Cookie を設定します。

30

サンプルアプリケーションのインストールMobile SDK 4.3 for Android および iOS の使用開始

第 6 章 Mobile SDK Labs へようこそ

Mobile SDK Labs では、現在テスト中の新しいテクノロジや、急速な進化に伴い不安定になる可能性があるテクノロジについての情報が共有されます。Mobile SDK アプリケーションの最先端テクノロジをお試しになる場合は、ここで各リリースの情報を確認してください。

トピック:

• Salesforce MobileSDK の React Native

• Polymer を使用するモバイル UI 要素

Salesforce Mobile SDK Labs の概要

Salesforce は、開発者が思いどおりにモバイルアプリケーションを作成できるように尽力しています。ニーズに最も適したテクノロジを自由に使用できることを目標としています。モバイル開発の世界では、猛烈なスピードで技術革新が進んでいます。ほぼ毎週、新しいツール、フレームワーク、ライブラリ、設計パターンが登場しています。これらのテクノロジのいくつかは本番アプリケーションとして十分な安定性と安全性があり、主流となりますが、その他のテクノロジは消滅していきます。Mobile SDK

チームは、SDK ライブラリ、サンプル、およびリソースで新しいテクノロジを使用するために常にテストを行っています。Salesforce Mobile SDK Labs では、調査中のサードパーティツールとフレームワークを試すことができます。Mobile SDKはコミュニティの協力を得て作成されているため、お客様のフィードバックを尊重し、多くの場合フィードバックを意思決定の際に考慮します。Google+ のSalesforceMobileSDK コミュニティでフィードバックをお寄せください。

警告: Salesforce では、Salesforce Mobile SDK Labs のアプリケーションおよびコードは正式にサポートされていません。本番アプリケーションでこれらのプロジェクトを使用する場合は注意が必要です。

31

Salesforce Mobile SDK の React Native

React Nativeは、JavaScript、CSS、およびマークアップを使用してネイティブ UI 要素に直接アクセスできるサードパーティのフレームワークです。このテクノロジを特別な Mobile SDK ネイティブモジュールと組み合わせて、ネイティブリソースを使用した迅速な開発を行うことができます。Mobile SDK は、当初から次の 2 種類のモバイルアプリケーションをサポートしています。• ネイティブアプリケーション: 最適なユーザ環境とパフォーマンスを提供します。ただし、サポートするモ

バイルプラットフォームごとに異なる開発テクノロジを使用する必要があります。• ハイブリッドアプリケーション: プラットフォーム間で JavaScript と CSS コードを共有できますが、基礎とな

る汎用 Web ビューがユーザ環境に悪影響を及ぼす可能性があります。Mobile SDK 4.0 以降では、3 つ目のオプションとして React Native があります。React Native は、JavaScript 開発のクロスプラットフォームの利点とネイティブアプリケーションのプラットフォーム固有の「デザイン」が 1 つになったアプリケーションです。さらに、開発者環境のスタイルと簡便性はハイブリッド開発に匹敵します。• レイアウトとスタイル設定には、広く知られている柔軟な Web テクノロジ (JavaScript、CSS、およびマーク

アップ) を使用します。• コンパイルは必要ありません。ブラウザを更新するだけで変更を確認できます。• デバッグには、任意のブラウザの開発者ツールを使用できます。• すべてのビューはネイティブで表示されるため、顧客にネイティブアプリケーションのユーザ環境を提供

できます。Mobile SDK 4.3 は React Native 0.30.0 を使用します。React Native 0.30.0 のソースコードおよびドキュメントは、github.com/facebook/react-native/releases/ の 0.30.0 タグの下にあります。

メモ: React Nativeは完全にサポートされているアプリケーション開発オプションですが、このフレームワークは急速に進化し続けているため、Labs 内で提供しています。

Mobile SDK 4.3 の React Native の新機能• バージョンの更新 — Mobile SDK は、React Native バージョン 0.30.0 で構築されるようになりました。

Android での使用開始Android で React Native の準備を整える手順は、次のとおりです。1. React Native に必要なソフトウェアをインストールします。facebook.github.io/react-native/docs/で「Getting Started」

の「Requirements」および「iOS Setup」を参照してください。2. 「Android のインストール」の説明に従って、最新バージョンの forcedroid をインストールします。Android 用の React Native プロジェクトを作成するには、React Native テンプレートを含む forcedroid を使用します。プロジェクトタイプとして react_native を指定します。対話型 forcedroid の使用例$ forcedroid createEnter your application type (native, react_native, hybrid_remote, or hybrid_local):react_native...

32

Salesforce Mobile SDK の React NativeMobile SDK Labs へようこそ

forcedroid コマンドラインパラメータの使用例$ forcedroid create --apptype="react_native" --appname="packagetest"--targetdir="PackageTest" --packagename="com.acme.mobileapps"

これで、React Native アプリケーションの開発を始める準備が整いました。

iOS での使用開始iOS で React Native の準備を整える手順は、次のとおりです。1. React Native に必要なソフトウェアをインストールします。facebook.github.io/react-native/docs/で「Getting Started」

の「Requirements」および「iOS Setup」を参照してください。2. 「iOS のインストール」の説明に従って、最新バージョンの forceios をインストールします。iOS 用の React Native プロジェクトを作成するには、React Native テンプレートを含む forceios を使用します。プロジェクトタイプとして react_native を指定します。対話型 forceios の使用例$ forceios createEnter your application type (native, native_swift, react_native, hybrid_remote,hybrid_local): react_native...

forceios コマンドラインパラメータの使用例$ forceios create --apptype="react_native" --appname="packagetest"--companyid="com.acme.mobileapps" --organization="Acme Widgets, Inc."--outputdir="PackageTest" --packagename="com.test.mobileapps"

これで、React Native アプリケーションの開発を始める準備が整いました。

Mobile SDK ネイティブコンポーネントと React Native の併用React Native アプリケーションは、次のネイティブブリッジを使用して JavaScript でMobile SDKにアクセスします。• react.force.oauth

• react.force.network

• react.force.smartstore

• react.force.smartsync

これらのブリッジは、ハイブリッドアプリケーションで使用される Mobile SDK コンポーネントと似ています。

メモ: React Native で forcetk ライブラリを使用することはできません。

React Native アプリケーション用の Mobile SDK ネイティブモジュールMobile SDKには、ネイティブMobile SDK機能への JavaScript ブリッジとして機能する React Native 用のネイティブモジュールが備えられています。

33

React Native アプリケーション用の Mobile SDK ネイティブモジュール

Mobile SDK Labs へようこそ

OAuthOAuth ブリッジは、Cordova の OAuth プラグインと似ています。使用方法

var oauth = require ("./react.force.oauth");

メソッドoauth.getAuthCredentials(success, fail);oauth.logout();

NetworkNetwork ブリッジは、ハイブリッドアプリケーションの forcetk.mobilesdk.js ライブラリと似ています。使用方法

var oauth = require ("./react.force.net");

メソッドnet.setApiVersion(version);net.getApiVersion();net.versions(callback, error);net.resources(callback, error);net.describeGlobal(callback, error);net.metadata(objtype, callback, error);net.describe(objtype, callback, error);net.describeLayout(objtype, recordTypeId, callback, error);net.create(objtype, fields, callback, error);net.retrieve(objtype, id, fieldlist, callback, error);net.upsert(objtype, externalIdField, externalId, fields, callback, error);net.update(objtype, id, fields, callback, error);net.del(objtype, id, callback, error);net.query(soql, callback, error);net.queryMore( url, callback, error);net.search(sosl, callback, error);

SmartStoreSmartStore ブリッジは、Cordova の SmartStore プラグインと似ています。ただし、プラグインとは異なり、React

Native では最初の引数は省略できません。使用方法

var oauth = require ("./react.force.smartstore");

メソッドsmartstore.buildAllQuerySpec(indexPath, order, pageSize,

selectPaths);smartstore.navigator.smartstore.buildExactQuerySpec(

path, matchKey, pageSize, order, orderPath, selectPaths);smartstore.navigator.smartstore.buildRangeQuerySpec(

34

React Native アプリケーション用の Mobile SDK ネイティブモジュール

Mobile SDK Labs へようこそ

path, beginKey, endKey, order, pageSize, orderPath, selectPaths);smartstore.navigator.smartstore.buildLikeQuerySpec(

path, likeKey, order, pageSize, orderPath, selectPaths);smartstore.navigator.smartstore.buildMatchQuerySpec(

path, matchKey, order, pageSize, orderPath, selectPaths);smartstore.buildSmartQuerySpec(smartSql, pageSize);smartstore.getDatabaseSize(isGlobalStore, successCB, errorCB);smartstore.registerSoup(isGlobalStore, soupName, indexSpecs,

successCB, errorCB);smartstore.removeSoup(isGlobalStore, soupName, successCB, errorCB);smartstore.getSoupIndexSpecs(isGlobalStore, soupName, successCB,

errorCB);smartstore.alterSoup(isGlobalStore, soupName, indexSpecs, reIndexData,

successCB, errorCB);smartstore.reIndexSoup(isGlobalStore, soupName, paths, successCB,

errorCB);smartstore.clearSoup(isGlobalStore, soupName, successCB, errorCB);smartstore.showInspector(isGlobalStore);smartstore.soupExists(isGlobalStore, soupName, successCB, errorCB);smartstore.querySoup(isGlobalStore, soupName, querySpec,

successCB, errorCB);smartstore.runSmartQuery(isGlobalStore, querySpec, successCB, errorCB);smartstore.retrieveSoupEntries(isGlobalStore, soupName, entryIds,

successCB, errorCB);smartstore.upsertSoupEntries(isGlobalStore, soupName, entries,

successCB, errorCB);smartstore.upsertSoupEntriesWithExternalId(isGlobalStore, soupName,

entries, externalIdPath, successCB, errorCB);smartstore.removeFromSoup(isGlobalStore, soupName, entryIds,

successCB, errorCB);smartstore.moveCursorToPageIndex(isGlobalStore, cursor, newPageIndex,

successCB, errorCB);smartstore.moveCursorToNextPage(isGlobalStore, cursor, successCB,

errorCB);smartstore.moveCursorToPreviousPage(isGlobalStore, cursor, successCB,

errorCB);smartstore.closeCursor(isGlobalStore, cursor, successCB, errorCB);

SmartSyncSmartSync ブリッジは、Cordova の SmartSync プラグインと似ています。ただし、プラグインとは異なり、React

Native では最初の引数は省略できません。使用方法

var oauth = require ("./react.force.smartsync");

メソッドsmartsync.syncDown(isGlobalStore, target, soupName, options, successCB, errorCB);smartsync.reSync(isGlobalStore, syncId, successCB, errorCB);smartsync.syncUp(isGlobalStore, target, soupName, options, successCB, errorCB);smartsync.getSyncStatus(isGlobalStore, syncId, successCB, errorCB);

35

React Native アプリケーション用の Mobile SDK ネイティブモジュール

Mobile SDK Labs へようこそ

React Native を使用した Mobile SDK サンプルアプリケーションMobile SDK の React Native を把握する最適な方法は、サンプルコードで学習することです。Mobile SDK には、SmartSyncExplorer アプリケーションの 4 つの実装があります。• Objective-C (iOS ネイティブ用)

• Java (Android ネイティブ用)

• HTML/JavaScript (iOS と Android のハイブリッド用)

• JavaScript と React (iOS と Android での React Native 用)

AndroidiOS実装

ネイティブ (Objective-C/Java) 1. SalesforceMobileSDK-Android GitHub

リポジトリをコピーします。1. SalesforceMobileSDK-iOS GitHub リポ

ジトリをコピーします。2. SalesforceMobileSDK-Android プロ

ジェクトを Android Studio にインポートします。

2. Xcode でSalesforceMobileSDKワークスペースを開きます。

3. SmartSyncExplorer アプリケーション (native/NativeSampleApps

3. SmartSyncExplorer アプリケーション (NativeSamples ワーク

プロジェクトフォルダにある) を実行します。

スペースフォルダにある) を実行します。

ハイブリッド (HTML/JavaScript) 1. SalesforceMobileSDK-Android GitHub

リポジトリをコピーします。1. SalesforceMobileSDK-iOS GitHub リポ

ジトリをコピーします。2. SalesforceMobileSDK-Android プロ

ジェクトを Android Studio にインポートします。

2. Xcode でSalesforceMobileSDKワークスペースを開きます。

3. SmartSyncExplorer アプリケーション (hybrid/HybridSampleApps

3. SmartSyncExplorerHybridアプリケーション (HybridSamples

プロジェクトフォルダにある) を実行します。

ワークスペースフォルダにある)

を実行します。

React Native (JavaScript と React) 1. SmartSyncExplorerReactNative GitHub

リポジトリをコピーします。1. SmartSyncExplorerReactNative GitHub

リポジトリをコピーします。2. ターミナルウィンドウまたはコ

マンドプロンプト2. ターミナルウィンドウまたはコ

マンドプロンプトで、./install.sh (Mac) またはで、./install.sh (Mac) またはcscript install.vbs

(Windows) を実行します。cscript install.vbs

(Windows) を実行します。3. cd を実行して app フォルダに

移動し、npm startを実行します。

3. cd を実行して app フォルダに移動し、npm startを実行します。

36

React Native を使用した Mobile SDK サンプルアプリケーション

Mobile SDK Labs へようこそ

AndroidiOS実装

4. Xcode で app/ios フォルダを開きます。

4. Android Studio で app/android

フォルダを開きます。5.5. SmartSyncExplorerReactNative

アプリケーションを実行します。

SmartSyncExplorerReactNative

アプリケーションを実行します。

React Native の SmartSyncExplorer に関するいくつかの注意事項

表 1 : 主要なフォルダとファイル説明パス

開始時の説明。README.md

連動関係 (iOS/Android SDK)。./install.sh (Mac) または cscript install.vbs (Windows) を実行したときにダウンロードされます。

external

iOS アプリケーション。app/ios

Android アプリケーション。app/android

アプリケーションの JavaScript ソースファイル。app/js

表 2 : React コンポーネント説明コンポーネントファイル

Android の開始スクリプト。app/js/index.android.js

iOS の開始スクリプト。app/js/index.ios.js

ルートコンポーネント (アプリケーション全体) (iOS と Android)。

SmartSyncExplorerReactNativeapp/js/App.js

検索画面 (iOS と Android)。SearchScreenapp/js/SearchScreen.js

1 つの取引先責任者を表示および編集するために使用します (iOS とAndroid)。

ContactScreenapp/jsContactScreen.js

検索画面の検索バー (iOS)。SearchBarapp/js/SearchBar.ios.js

検索画面の検索バー (Android)。SearchBarapp/js/SearchBar.android.js

検索画面内の結果リストの 1 行 (iOS

と Android)。ContactCellapp/js/ContactCell.js

37

React Native を使用した Mobile SDK サンプルアプリケーション

Mobile SDK Labs へようこそ

説明コンポーネントファイル

検索結果画面で使用されるイニシャルが含まれた色付きの円 (iOS とAndroid)。

ContactBadgeapp/js/ContactBadge.js

取引先責任者画面で使用される項目の名前と値 (iOS と Android)。

Fieldapp/js/Field.js

SmartStore とサーバを操作します(SmartSync 経由)。

StoreMgrapp/js/StoreMgr.js

メモ: ほとんどのコンポーネントは、iOS と Android で共有されます。ただし、いくつかのコンポーネントはプラットフォーム固有です。

ログインの延期Mobile SDKの初期バージョンのReact Nativeでは、起動時に常にSalesforceログイン画面が表示されます。ただし、これらのアプリケーションは認証を後の時点まで延期することで利点を得られる場合があります。Mobile SDK

4.2 の React Native 以降、アプリケーションの任意の論理的場所までログインを延期できます。遅延ログインの実装は 2 ステップからなるプロセスです。1. iOS または Android ネイティブコンテナアプリケーションでは、Mobile SDK ネイティブメソッドをコールして

起動時の認証を無効にします。2. React コードで、認証を開始する時点で Mobile SDK JavaScript 関数をコールします。実装の詳細は、この後で説明します。

ステップ 1: 起動時のログインを無効にするiOS (Objective-C):

デフォルトでは、起動時に Salesforce ログイン画面が表示されます。この動作を無効にするには、SalesforceSDKManager の authenticateAtLaunch プロパティを NO に設定します。1. AppDelegate.m ファイルを編集します。2. 次の行を変更します。

[SalesforceSDKManager sharedManager].authenticateAtLaunch = YES;

変更後[SalesforceSDKManager sharedManager].authenticateAtLaunch = NO;

Android (Java):

38

ログインの延期Mobile SDK Labs へようこそ

デフォルトでは、起動時にSalesforceログイン画面が表示されます。この動作を無効にするには、MainActivity

クラス (または SalesforceReactActivity をサブクラス化するクラス) の shouldAuthenticate() メソッドを次のように変更します。@Overridepublic boolean shouldAuthenticate() {

return false;}

ステップ 2: React (JavaScript) で認証を開始する認証プロセスを開始するには、次の react.force.oauth.js 関数をコールします。function authenticate(success, fail)

この関数は、成功コールバック関数と失敗コールバック関数の 2 つの引数を取ります。認証に失敗すると、失敗コールバックが呼び出されます。認証に成功すると、次のキーを含む辞書と共に成功コールバックが呼び出されます。• accessToken

• refreshToken

• clientId

• userId

• orgId

• loginUrl

• instanceUrl

• userAgent

• communityId

• communityUrl

バイナリコンテンツのアップロードMobile SDK 4.2 以降、バイナリアップロード機能をサポートする任意の force.com エンドポイントにバイナリコンテンツをアップロードできます。react.force.net.js の sendRequest() メソッドには、fileParams という新しい省略可能なパラメータがあります。function sendRequest(endPoint, path, successCB, errorCB, method, payload, headerParams,fileParams)

このパラメータの形式は次のようになります。{

<fileParamNameInPost>: // value depends on the endpoint{

fileMimeType:<someMimeType>,fileUrl:<fileUrl>, // url to file to uploadfileName:<fileNameForPost>

39

バイナリコンテンツのアップロードMobile SDK Labs へようこそ

}}

次に例を示します。{

fileUpload:{

fileMimeType:'image/jpeg',fileUrl:localPhotoUrl,fileName:'pic.jpg'

}}

例: github.com/wmathurin/MyUserPicReactNativeサンプルアプリケーションはバイナリアップロードを示しています。このサンプルでは、プロファイル写真を変更できます。新しい写真のバイナリアップロードは、UserPic.js ファイルの uploadPhoto() 関数で行われます。このサンプルの getUserInfo() 関数での sendRequest() コールを次に示します。getUserInfo(callback) {

forceClient.sendRequest('/services/data','/v36.0/connect/user-profiles/' + this.state.userId + '/photo',(response) => {

callback(response);},(error) => {

console.log('Failed to upload user photo:' + error);},'POST',{},{'X-Connect-Bearer-Urls': 'true'},{fileUpload:

{fileUrl:localPhotoUrl,fileMimeType:'image/jpeg',fileName:'pic.jpg'

}}

);},

Polymer を使用するモバイル UI 要素

モバイルアプリケーション開発者にとって幸せなことは、一連の API に拘束される別の詳細ページを作成するのではなく、革新的な機能の作成に時間をかけることです。Salesforceモバイル UI 要素ライブラリは、Google のPolymer フレームワークで Force.com API をラップして、HTML5 の迅速な開発を実現します。モバイル UI 要素を使用すると、HTML および JavaScript 開発者は、既知のテクノロジで強力な Salesforce モバイルアプリケーションを開発できます。オープンソースのモバイル UI 要素のプロジェクトには、柔軟性が高く、驚くほど簡単に習得できるコンポーネントライブラリがあらかじめ用意されています。モバイル UI 要素アプリケーションは、次の方法でリリースできます。

40

Polymer を使用するモバイル UI 要素Mobile SDK Labs へようこそ

• Visualforce ページでリリースする• www.heroku.com または別のサードパーティサービスのリモートホストされるページでリリースする• Salesforce Mobile SDKで提供されるハイブリッドコンテナを使用するスタンドアロンアプリケーションとして

リリースするモバイル UI 要素は、Google の Polymer フレームワークに基づいた、オープンソースのサポート対象外ライブラリです。複雑なモバイルアプリケーションを作成するために組み合わせ可能な、基本的なビルディングブロックを提供します。HTML 開発者はこのコンポーネントライブラリを使用して、複雑なモバイルフレームワークや設計パターンの詳しい知識を習得せずに、モバイルアプリケーションをすばやく簡単に作成できます。モバイル UI 要素のソースコードは、github.com/ForceDotComLabs/mobile-ui-elements にあります。

サードパーティのコードモバイル UI 要素ライブラリでは、次のサードパーティのコンポーネントを使用します。• Polymer: 新しい拡張機能および機能を最新の HTML5 ブラウザに追加するために使用される JavaScript ライブラ

リ。Web コンポーネントで構築され、最新ブラウザ上で進化している Web プラットフォームを使用するよう設計されています。

• jQuery: JavaScript の作成を簡単にする JavaScript ライブラリ。• Backbone.js: モデル–ビュー–プレゼンター (MVP) アプリケーション設計パラダイムを提供する JavaScript ライブ

ラリ。• Underscore.js: JavaScript 用の「ユーティリティ関連」ライブラリ。• Ratchet: 単純な HTML、CSS、JavaScript コンポーネントを使用するプロトタイプ iPhone アプリケーション。次の参照セクションでは、現在使用可能な要素について説明します。

force_selector_listforce-selector-list 要素は core-selector 要素の拡張で、force-sobject-collection 要素を囲むラッパーを提供します。force-selector-list は、セレクタ機能を必要とするリスト UI 要素のベースとして機能します。ユーザが行をタップすると、選択された属性が自動的に更新されます。

例<force-selector-list sobject="Account" querytype="mru"></force-selector-list>

force-selector-relatedlistforce-selector-relatedlist 要素は、core-selector 要素を拡張したものであり、force-sobject-collection 要素を使用して関連 sObject のレコードを取得します。force-selector-relatedlist は、レコードの関連リストを表示しセレクタ機能も必要とする UI 要素の基本要素です。

41

force_selector_listMobile SDK Labs へようこそ

例<force-selector-relatedlist related="{{related}}"></force-selector-relatedlist>

force-sobjectforce-sobject 要素は、Polymer 要素の SmartSync Force.SObject をラップします。force-sobject 要素の機能は、次のとおりです。• キャッシュ用のオフラインストアの自動管理を提供する• SmartSync SObject モデルとやりとりするための DOM ベースの単純なインターフェースを提供する• 他の Polymer 要素が SmartSync を簡単に使用できるようにする

例<force-sobject sobject="Account" recordid="001000000000AAA"></force-sobject>

force-sobject-collectionforce-sobject-collection 要素は、SmartSync Force.SObjectCollection オブジェクトの Polymer 下位ラッパーです。この要素の機能は、次のとおりです。• キャッシュ用のオフラインデータストアを自動的に管理する (コンテナ内で実行されている場合)

• SmartSync とやりとりするための DOM ベースの単純なインターフェースを提供する• 他の Polymer 要素が SmartSync データを簡単に使用できるようにする

例<force-sobject-collection sobject="Account" querytype="mru"></force-sobject-collection>

force-sobject-layoutforce-sobject-layout 要素は、特定の sObject レコードのレイアウト情報を提供します。この要素はdescribeLayout API コールをラップします。レイアウト情報は既存のセッションのメモリにキャッシュされ、オフラインで使用できるように SmartStore に保存されます。force-sobject-layout 要素はまた、force-ui-detail や force-sobject-related など、ページレイアウトに依存する要素の基本定義を提供します。

例<force-sobject-layout sobject="Account"></force-sobject-layout>

42

force-sobjectMobile SDK Labs へようこそ

force-sobject-relatedlistsforce-sobject-relatedlists要素により、sObject レコードの関連リストが表示できます。関連リスト設定をページレイアウト設定から取得するために、force-sobject-layout 要素を埋め込みます。特定の sObject

種別の関連リスト設定を解析します。recordid属性が指定されている場合は、関連レコード項目を取得するために SOQL/キャッシュクエリも生成します。

例<force-sobject-relatedlists sobject="Account"recordid="001000000000AAA"></force-sobject-relatedlists>

force-sobject-storeforce-sobject-store 要素は、Polymer 要素の SmartSync Force.StoreCache をラップします。この要素の機能は、次のとおりです。• sObject の種別ごとに SmartStore スープのライフサイクルを自動管理する• sObject での参照関係に基づいてインデックス指定を自動作成する• SmartSync SObject モデルとやりとりするための DOM ベースの単純なインターフェースを提供する• 他の Polymer 要素が SmartStore データを簡単に使用できるようにする

例<force-sobject-store sobject="Account"></force-sobject-store>

force-ui-appforce-ui-app 要素は、アプリケーションの基本のスタイルと構造を提供する最上位の UI 要素です。この要素は、Polymer レイアウト機能を使用してページ上で柔軟なセクションを作成できるようにします。この機能は、分割ビューパネルを含む単一ページビューで便利です。メインセクションのすべての子セクションでは、「コンテンツ」クラスを指定して正しいスタイルを適用する必要があります。

例Visualforce コンテキストで使用する場合<force-ui-app multipage="true"></force-ui-app>

force-ui-detailforce-ui-detail 要素により、Salesforce レコードの全画面表示が可能になります。この要素は、force-sobject-layout 要素を使用してレコードのページレイアウトを取得します。また、sObject ですべての CRUD 操作を許可するために、force-sobject 要素の埋め込みも行います。デフォルトのスタイルを継承するには、この要素が常に force-ui-app の子である必要があります。

43

force-sobject-relatedlistsMobile SDK Labs へようこそ

例<force-ui-detail sobject="Account" recordid="001000000000AAA"></force-ui-detail>

force-ui-listforce-ui-list 要素により、任意の sObject レコードのリストが表示できます。属性を使用して、特定のレコードセットを表示するようにこの要素を設定できます。適切なスタイルを継承するには、この要素が常にforce-ui-app の子である必要があります。

例<force-ui-list sobject="Account" querytype="mru"></force-ui-list>

force-ui-relatedlistforce-ui-relatedlist要素により force-selector-relatedlistelementが拡張され、sobjectレコードの関連レコードリストが表示されます。デフォルトのスタイルを継承するには、この要素が常にforce-ui-app の子である必要があります。

例<force-ui-relatedlist related="{{related}}"></force-ui-relatedlist>

44

force-ui-listMobile SDK Labs へようこそ

第 7 章 ネイティブ iOS の開発

Salesforce Mobile SDK では、iOS でモバイルアプリケーションを開発するためのライブラリとサンプル Xcode プロジェクトが提供されます。

トピック:

• iOS ネイティブクイックスタート iOS ネイティブ SDK では、次の 2 つの重要な機能が提供されます。

• OAuth2 ログインプロセスの自動化。これにより、OAuth をアプリケーションに統合しやすくなります。

• ネイティブ iOS の要件

• REST API へのアクセス。アクセスをできるかぎり簡略化するインフラストラクチャクラスが使用されます。

• forceios を使用したiOS プロジェクトの作成

forceios アプリケーションを使用してネイティブアプリケーションを作成すると、完全に機能するアプリケーションとしてプロジェクトが開始します。このアプリケー• CocoaPods と

Mobile SDK の使用 ションでは、Salesforce 組織に接続し、簡単なクエリを実行できます。多くの操作はできませんが、設計どおりに動作することを確認できます。• ネイティブ iOS アプ

リケーションの開発

• チュートリアル: ネイティブ iOSWarehouse アプリケーションの作成

• iOS サンプルアプリケーション

45

iOS ネイティブクイックスタート

すばやく開始する手順は、次のとおりです。1. ネイティブ iOS 要件をすべて満たしていることを確認します。2. Mobile SDK for iOSをインストールします。必要に応じて、代わりにMobile SDK GitHub リポジトリからMobile SDK

をインストールすることもできます。3. テンプレートアプリケーションを実行します。

ネイティブ iOS の要件

Mobile SDK 4.3 を使用した iOS の開発には、次のソフトウェアが必要です。• iOS 8 以降。• Xcode — バージョン 7 以降 (最新バージョンを推奨)。• CocoaPods (cocoapods.org)。• forceios、バージョン 4.3。• 接続アプリケーションが存在する Salesforce Developer Edition 組織。

メモ: バージョン 4.0 以降、Mobile SDK for iOS では、Cocoa Touch 動的フレームワークがサポートされます。

関連トピック:

iOS のインストール

forceios を使用した iOS プロジェクトの作成

アプリケーションを作成するには、ターミナルウィンドウで forceios を使用します。forceios ユーティリティでは、2 つの方法でアプリケーションを設定できます。• forceios アプリケーションからプロンプトが表示されたときに、アプリケーションオプションを対話形式で

設定する。• forceios コマンドラインコールの引数としてアプリケーションオプションを指定する。

メモ: 必ず forceios を使用する前に CocoaPods をインストールしてください。「iOS のインストール」を参照してください。

プロジェクトタイプforceios ユーティリティによってプロジェクトタイプを選択するように求められます。プロジェクトタイプオプションにより、最も生産性の高い開発環境で Mobile SDK を使用するための柔軟性を得られます。

言語アーキテクチャアプリケーション種別

Objective-Cネイティブnative

46

iOS ネイティブクイックスタートネイティブ iOS の開発

言語アーキテクチャアプリケーション種別

Swiftネイティブnative_swift

JavaScript with ReactReact Nativereact_native

JavaScript、CSS、HTML5ハイブリッドhybrid_local

JavaScript、CSS、HTML5、ApexVisualforce を使用するハイブリッドhybrid_remote

ネイティブ iOS アプリケーションを作成するには、native または native_swift を指定します。

対話形式での forceios の使用forceios を対話形式で使用するには、ターミナルウィンドウを開いて、「forceios create」と入力します。設定値ごとに、forceios ユーティリティによってプロンプトが表示されます。

コマンドライン引数での forceios の使用必要に応じて、コマンドライン引数として forceios オプションを指定できます。使用方法に関する情報を表示するには、引数を指定せずに「forceios」と入力します。使用可能なオプションのリストが表示されます。$ forceiosUsage:forceios create

--apptype=<Application Type> (native, native_swift, react_native, hybrid_remote,hybrid_local)

--appname=<Application Name>--companyid=<Company Identifier> (com.myCompany.myApp)--organization=<Organization Name> (Your company's name)--startpage=<App Start Page> (The start page of your remote app.Only required for hybrid_remote)

[--outputdir=<Output directory> (Defaults to current workingdirectory)]

[--appid=<Salesforce App Identifier> (The Consumer Key for yourapp. Defaults to the sample app.)]

[--callbackuri=<Salesforce App Callback URL (The Callback URLfor your app. Defaults to the sample app.)]

この情報を使用して、「forceios create」の後にオプションと値を続けて入力します。たとえば、Objective-C

でネイティブアプリケーションを開発する場合、次のようになります。$ forceios create --apptype="native" --appname="package-test"--companyid="com.acme.mobile_apps" --organization="Acme Widgets, Inc."--outputdir="PackageTest" --packagename="com.test.my_new_app"

また、Swift でネイティブアプリケーションを開発する場合、次のようになります。$ forceios create --apptype="native_swift" --appname="package-test"--companyid="com.acme.mobile_apps" --organization="Acme Widgets, Inc."--outputdir="PackageTest" --packagename="com.test.my_new_app"

47

forceios を使用した iOS プロジェクトの作成ネイティブ iOS の開発

XCode で新規プロジェクトを開くforceios テンプレートを使用して作成されたアプリケーションは、標準で実行準備が整っています。アプリケーションの作成スクリプトが完了したら、プロジェクトを Xcode で開いて実行できます。1. Xcode で [File (ファイル)] > [Open (開く)] を選択します。2. 指定した出力フォルダに移動します。3. native、native_swift、および react_native アプリケーションの場合、CocoaPods で生成されたワー

クスペースファイルを開きます。hybrid_local および hybrid_remote アプリケーションの場合、アプリケーションの xcodeproj ファイルを開きます。

4. Xcode での作成が完了したら、[Run (実行)] ボタンをクリックします。

関連トピック:

forceios パラメータ

Xcode プロジェクトのテンプレートアプリケーションを実行するXcode プロジェクトのテンプレートには、すぐに実行できるサンプルアプリケーションが含まれています。1. [Command-R]キーを押すと、デフォルトのテンプレートアプリケーションが iOS シミュレータで実行されま

す。2. アプリケーションは、起動時に OAuth 認証フローで開始し、認証ページが表示されます。ログイン情報を

入力し、[Login (ログイン)] をクリックします。3. 許可を求められたら、[許可] をタップします。これで、サンプルプロジェクトをコンパイルし、実行できるようになりました。これは、OAuth2 を介して組織にログインし、select Name from Account SOQL クエリを発行し、結果を UITableView インスタンスに表示する簡単なアプリケーションです。

CocoaPods と Mobile SDK の使用

CocoaPods には、Mobile SDK モジュールを既存の Xcode プロジェクトにマージするための便利なメカニズムが備えられています。Mobile SDK 4.0 以降、forceios は CocoaPods を使用してプロジェクトを作成します。開発者が CocoaPods を手動で使用して Mobile SDK を既存の iOS アプリケーションに追加することもできます。Mobile SDK for iOS 4.0 以降を使用するには、CocoaPods をインストールする必要があります。CocoaPods に慣れていない方は、www.cocoapods.org にあるドキュメントをまずお読みください。Mobile SDK には、Mobile SDK モジュールごとに CocoaPods pod の仕様 (podspecs) が用意されています。• SalesforceSDKCore — OAuth とパスコードを実装します。他のどの pod も直接的または間接的にこの pod

と連動します。

48

Xcode プロジェクトのテンプレートアプリケーションを実行する

ネイティブ iOS の開発

• SalesforceNetwork — ネットワーキングライブラリ (セッション期限が切れたときに透過的なトークンを更新)

• SalesforceRestAPI — Salesforceデータにアクセスするための REST API ラッパー。SalesforceNetworkと連動します。

• FMDB — SQLite に対するサードパーティの Objective—C ラッパーである FMDB の Mobile SDK fork。この fork はカスタマイズされたログを実装し、全文検索クエリをサポートする SQLCipher をインポートします。

• SmartStore — セキュアなオフラインストレージを実装します。FMDB と連動します。• SmartSync — オフライン同期を実装します。SalesforceRestAPI および SmartStore と連動します。• SalesforceReact — React JavaScript とマークアップで記述されたアプリケーションの Salesforce Mobile SDK

React Native ブリッジを実装します。SmartSync と連動します。次の図は、仕様間の連動関係を示しています。この図では、連動する側の仕様から連動される側に向かって矢印が伸びています。

pod を宣言すると、その pod の連動関係チェーンのすべてを自動的に取得します。たとえば、SalesforceReact

の pod を宣言すると、Mobile SDK のチェーン全体を自動的に取得します。github.com/forcedotcom/SalesforceMobileSDK-iOS-Specs リポジトリのすべてのバージョンの Mobile SDK podspec にアクセスできます。github.com/forcedotcom/SalesforceMobileSDK-iOSリポジトリから現在のバージョンを取得することもできます。CocoaPods を通じて Mobile SDK を使用する手順は、次のとおりです。1. www.cocoapods.org の説明に従って cocoapods Ruby gem がインストールされていることを確認します。

49

CocoaPods と Mobile SDK の使用ネイティブ iOS の開発

2. プロジェクトの Podfile で、SalesforceMobileSDK-iOS-Specsリポジトリをソースとして追加します。必ず最初にこのエントリを CocoaPods ソースパスより前に配置します。target 'YourAppName' dosource 'https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Specs.git' # needs to befirstsource 'https://github.com/CocoaPods/Specs.git'...

3. アプリケーションにマージするMobile SDK podspec を参照します。たとえば、OAuth モジュールとパスコードモジュールをアプリケーションに追加する場合は、Podfile で SalesforceSDKCore pod を宣言します。以下に例を示します。target 'YourAppName' dosource 'https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Specs.git' # needs to befirstsource 'https://github.com/CocoaPods/Specs.git'

pod 'SalesforceSDKCore'

end

4. 他のモジュールを追加するには、pod コールを追加します。たとえば、REST API パッケージとネットワークパッケージを使用する場合は、SalesforceSDKCore に加えて SalesforceRestAPI pod とSalesforceNetwork pod を宣言します。以下に例を示します。target 'YourAppName' dosource 'https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Specs.git' # needs to befirstsource 'https://github.com/CocoaPods/Specs.git'

pod 'SalesforceSDKCore'pod ‘SalesforceNetwork’pod ‘SalesforceRestAPI’

end

5. Mobile SDK の次回のリリースで作業する場合は、SalesforceMobileSDK-iOS の不安定なブランチをコピーして、そのコピーからリソースを取り込みます。a. 目的の commit で github.com/forcedotcom/SalesforceMobileSDK-iOS をローカルにコピーします。b. ターミナルウィンドウで、コピーのルートディレクトリにある ./install.sh を実行します。c. Podfile の各 pod コールに、コピーを指し示す :path パラメータを追加します。次のコードは、ローカルコピーからリソースを取り込むように上記の例を再設定したものです。target 'YourAppName' dosource 'https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Specs.git' # need to befirstsource 'https://github.com/CocoaPods/Specs.git'

pod 'SalesforceSDKCore', :path => ‘/<path-to-clone-of>/SalesforceMobileSDK-iOS/’pod ‘SalesforceNetwork’, :path => ‘/<path-to-clone-of>/SalesforceMobileSDK-iOS/’

50

CocoaPods と Mobile SDK の使用ネイティブ iOS の開発

pod ‘SalesforceRestAPI’, :path => ‘/<path-to-clone-of>/SalesforceMobileSDK-iOS/’

end

6. ターミナルウィンドウで、プロジェクトディレクトリから pod installを実行します。CocoaPodsにより、要求された pod の連動関係のダウンロード、プロジェクトへのマージ、新しくマージされたプロジェクトを含むワークスペースの作成が行われます。

重要: CocoaPods の実行後は必ず pod install で作成されたワークスペースからプロジェクトにアクセスします。たとえば、MyProject.xcodeprojを開くのではなく、MyProject.xcworkspaceを開きます。

7. マージされたアプリケーションでMobile SDK API を使用する場合は、次の重要なヒントを考慮してください。a. 二重引用符ではなく山かっこ (「<」および「>」) を使用して、ヘッダーファイルをインポートします。

次に例を示します。import <SalesforceRestAPI/SFRestAPI.h>

b. Swift アプリケーションについては、必ず Podfile で use_frameworks!を指定します。また、Swift ソースファイルで、ヘッダーファイルではなく、モジュールをインポートします。以下に例を示します。import SalesforceRestAPI

ネイティブ iOS アプリケーションの開発

ネイティブ iOS の Salesforce Mobile SDK には、Apple モバイルデバイスのアプリケーションを構築するために必要なツールが備えられています。SDK には、次の特性があります。• Salesforce REST API コールを簡単にするクラスとインターフェース• 完全に実装された OAuth ログインとパスコードのプロトコル• ユーザデータをオフラインで安全に管理するための SmartStore ライブラリネイティブ iOS SDK では、Objective-C コーディングに精通している必要があります。また、iOS アプリケーションの開発原則とフレームワークに関する知識も必要です。初めて使用する場合は、「Start Developing iOS Apps

Today」を使用して学習を開始することをお勧めします。他の前提条件は、「ネイティブ iOS の要件」を参照してください。一部のMobile SDKインターフェースでは、いくつかのメソッドとプロパティを上書きする必要があります。SDK

ヘッダー (.h) ファイルには、必須の上書きと省略可能な上書きを示すコメントが含まれています。

ログインとパスコードについてMobile SDK アプリケーションから Salesforce オブジェクトにアクセスするには、顧客が Salesforce サーバで組織にログインする必要があります。ログインフローが開始すると、アプリケーションの接続アプリケーション設定が Salesforce に送信されます。Salesforce は、ログイン画面をモバイルデバイスに投稿して応答します。必要に応じて、Salesforceシステム管理者は、ログイン後にパスコードを必要とするように接続アプリケーションを設定することができます。Mobile SDKでは、ログイン画面とパスコード画面の表示、および認証ハンドシェ

51

ネイティブ iOS アプリケーションの開発ネイティブ iOS の開発

イクの処理が行われます。これらの画面を表示するために、アプリケーションで何らかの操作をする必要はありません。ただし、ログインフローおよび OAuth トークンの処理方法を理解しておくことが重要です。「PIN

セキュリティについて」および「OAuth2.0 認証フロー」を参照してください。

メモ: Mobile SDK for iOS では、Touch ID を使用して PIN を提供できます。初めてアプリケーションを起動した場合、顧客は PIN を入力する必要があります。アプリケーションを初めて起動すると、Touch ID またはキーボードを使用して PIN を入力するように求められます。

メモリ管理についてMobile SDK 2.0 以降では、ネイティブ iOS アプリケーションで Automatic Reference Counting (ARC) を使用して、オブジェクトメモリが管理されます。オブジェクトを割り当てたあとに、割り当て解除することを覚えておく必要はありません。ARC の構文、ガイドライン、ベストプラクティスについては、「メモリ管理について」の「Mac

Developer Library」を参照してください。

アプリケーションフローの概要forceios で作成されたプロジェクトでは、AppDelegate、InitialViewController、およびRootViewController の 3 つのクラスが定義されています。AppDelegate オブジェクトでは、最初に表示するビューとして InitialViewControllerが読み込まれます。認証プロセスが完了すると、AppDelegate

オブジェクトにより、RootViewController に関連付けられたビューがアプリケーションのエントリポイントとして表示されます。Mobile SDK を使用して構築された iOS ネイティブアプリケーションは、他の iOS アプリケーションと同じ設計になります。main.m のソースファイルでは、アプリケーションの残りの部分のルートオブジェクトとなるUIApplicationMainオブジェクトが作成されます。UIApplicationMainコンストラクタでは、アプリケーションのライフサイクルを管理する AppDelegate オブジェクトが作成されます。AppDelegateでは、Salesforce 認証およびパスコードの活動を調整するために、Mobile SDKサービスオブジェクト (SalesforceSDKManager) が使用されます。ユーザが認証されると、AppDelegate からRootViewController オブジェクトに制御が移ります。

52

メモリ管理についてネイティブ iOS の開発

メモ: テンプレートアプリケーションで示すワークフローは一例にすぎません。AppDelegate およびサポートクラスをカスタマイズして、目的のワークフローにすることができます。たとえば、Salesforce認証を後の時点まで延期することができます。REST API コールを使用したデータの取得、データの表示、他のビューの起動、サービスの実行などを行うことができます。アプリケーションは、ユーザがアプリケーションを明示的に終了するか、デバイスが再起動されるまでメモリ内でアクティブのままになります。

関連トピック:

SalesforceSDKManager および SmartStoreSDKManager クラス

SalesforceSDKManager および SmartStoreSDKManager クラスSalesforceSDKManager クラスは、アプリケーション ID とブートストラップ設定を 1 つのコンポーネントに統合します。アプリケーション開発者によって提供された設定を使用して、認証とパスコード間の複雑なやりとりを管理します。つまり、SalesforceSDKManagerによって、開発者がブートストラッププロセスを制御する必要がなくなります。Mobile SDK テンプレートアプリケーションは、SalesforceSDKManager クラスを使用して開発者に代わってほとんどの Salesforce 固有の起動時の機能を実装します。SalesforceSDKManager は、PIN コード、OAuth 設定、その他のブートストラッププロセスを含む、アプリケーションに起動に関与するすべてのオブジェクトを管理および調整します。SalesforceSDKManagerを使用することで、これらのプロセス間のやりとりが適切な順序で行われることが保証され、起動フローの個々の部分はこれまでどおりカスタマイズできます。Mobile

SDK 3.0 以降では、すべての iOS ネイティブアプリケーションで SalesforceSDKManagerを使用してアプリケーション起動時の動作を管理する必要があります。

メモ: Mobile SDK 3.0 で導入された SalesforceSDKManager クラスは、既存の認証管理オブジェクトまたはイベントに代わるものではありません。むしろ、既存の起動管理オブジェクトのスーパーマネージャと言えます。既存のコードは引き続き問題なく動作しますが、開発者は最新の Mobile SDK バージョンとSalesforceSDKManager にアップグレードすることを強くお勧めします。

53

SalesforceSDKManager および SmartStoreSDKManager クラス

ネイティブ iOS の開発

SmartStoreSDKManager についてMobile SDK 4.0 では、SmartStoreライブラリがMobile SDKコアから独自の格納場所に移動されています。そのため、SmartStoreを使用するアプリケーションは SmartStoreSDKManagerクラスのインスタンスが必要になります。このクラスでは、コードの SalesforceSDKManagerが置き換わりません。代わりに、SmartStoreSDKManager

をインスタンスクラスとして使用するように、共有 SalesforceSDKManager インスタンスを設定します。以前のリリースから Mobile SDK 4.0 にアップグレードする SmartStore アプリケーションでは、次の手順を実行する必要があります。AppDelegate.m ファイルで次の手順を実行します。1. SmartStoreSDKManager ヘッダーをインポートします。

#import <SmartStore/SmartStoreSDKManager.h>

2. initメソッドで、[SalesforceSDKManager sharedManager]が最初に使用される前に次のコールを追加します。[SalesforceSDKManager setInstanceClass:[SmartStoreSDKManager class]];

このコールでのみ、SmartStoreSDKManager クラスを明示的に参照する必要があります。残りのコードは、以前と同じように機能します。

例については、SmartSyncExplorer サンプルアプリケーションのAppDelegate クラスを参照してください。

ライフサイクルSalesforceSDKManager はシングルトンオブジェクトです。このオブジェクトにアクセスするには、sharedManager クラスメッセージを送信します:

[SalesforceSDKManager sharedManager]

この共有オブジェクトは、アプリケーションが [SalesforceSDKManager sharedManager] を初めてコールしたときに一度だけ作成されます。他の 3 つのMobile SDKマネージャオブジェクトの代理として機能します。• SFUserAccountManager

• SFAuthenticationManager

• SFPasscodeManager

アプリケーションは次の 2 つのシナリオで SalesforceSDKManager オブジェクトを使用します。1. アプリケーション起動時に、AppDelegate の init および

application:didFinishLaunchingWithOptions: メソッドで使用2. アプリケーションの実行中に、ログアウト、トークンの期限切れ、またはトークンの取り消しが原因で現

在のユーザの OAuth トークンが無効になるたびに使用1 番目のシナリオのイベントは、アプリケーションのライフサイクルで 1 回のみ発生します。2 番目のシナリオは何度でも発生する可能性があります。Mobile SDKは無効なトークンを検出すると、SalesforceSDKManager

アプリケーション起動フローを再実行します。このフローには、アプリケーションで提供されるすべての関連イベントハンドラも含まれます。アプリケーションが再初期化されるときに望ましくないデータ損失や状態が発生することを避けるため、これらのイベントハンドラは慎重にコード化してください。

54

SalesforceSDKManager および SmartStoreSDKManager クラス

ネイティブ iOS の開発

アプリケーション起動フローapplication:didFinishLaunchingWithOptions: メッセージを受信したら、launch メッセージを共有SalesforceSDKManagerインスタンスに送信してアプリケーションを起動します。アプリケーションの接続アプリケーションにパスコードが必要な場合は、ブートストラッププロセスを続行する前に、SalesforceSDKManagerにユーザのパスコード確認画面が表示されます。次のダイアグラムに、このフローを示します。

重要なポイント:

• 接続アプリケーション定義の OAuth 設定でパスコードが要求されない場合、フローは直接 Salesforce 認証に進みます。

• 有効なアクセストークンが検出された場合、フローは Salesforce 認証をスキップします。

55

SalesforceSDKManager および SmartStoreSDKManager クラス

ネイティブ iOS の開発

• アクセストークンが検出されず、デバイスがオフラインの場合、認証モジュールによりエラーが発生し、ログイン画面に戻ります。SalesforceSDKManager によってこのイベントがアプリケーションに反映されることはありません。

• postLaunch イベントは、すべてのログイン情報とパスコードチャレンジが確認された後にのみ発生します。

このダイアグラムに表示されている内容の他に、アプリケーションでユーザの切り替えと転送通知設定がサポートされている場合、SalesforceSDKManager起動プロセスはそれらの機能もアプリケーションに委任します。ユーザがパスコードチャレンジか、Salesforceログインを失敗またはキャンセルした場合、postLogout

イベントが起動されてから、制御が AppDelegate に戻されます。postLaunch イベント後、ユーザがログアウトするかユーザの切り替えイベントが発生するまで、SalesforceSDKManager オブジェクトは再表示されません。このいずれかのイベントが発生すると、SalesforceSDKManagerからアプリケーションに通知されます。その時点で、アプリケーションのMobile SDK

の状態をリセットしてアプリケーションを再起動できます。

SalesforceSDKManager 起動イベントSalesforceSDKManager は、アプリケーションとデバイスの状態に応じてアプリケーションのブートストラッププロセスを指示します。ブートストラッププロセス中、起動シーケンスの重要な時点でいくつかのイベントが起動されます。これらのイベントを使用して、SalesforceSDKManager フローの完了後に独自のロジックを実行できます。フォアグラウンドの場合、アプリケーションのロジックを再開する前に、アプリケーションが postAppForeground イベントを受信するまで待機してください。

表 3 : 起動イベント説明イベント

すべての起動アクティビティの完了後に受信します。アプリケーションはビジネスプロセスを続行できます。

postLaunch

起動プロセス中に致命的なエラーが発生した場合に送信されます。

launchError

現在のユーザがログアウトした後、またはユーザがパスコードテストやログイン認証に失敗した場合に受信します。

postLogout

アプリケーションがフォアグラウンドに戻り、パスコード (該当する場合) が確認された後に受信します。

postAppForeground

このイベントは、認証が有効であることを示します。アプリケーションがこのイベントを受信したら、フォアグラウンドで処理する追加アクションを実行できます。

現在のユーザが変更された後に受信します。switchUser

56

SalesforceSDKManager および SmartStoreSDKManager クラス

ネイティブ iOS の開発

特定のイベントは他のイベントよりも優先されます。たとえば、起動中にパスコードの確認に失敗した場合、postLogoutイベントが起動されますが、postLaunchイベントは起動されません。優先度レベル間で、ランクの高いイベントがランクの低いイベントの代わりに起動されます。優先度の一覧を次に示します。1 が最も高い優先度レベルです。

表 4 : 起動イベントの優先度レベルコメントイベント優先度レベル

これらのイベントは他のすべてのイベントよりも優先されます。

postLogout、switchUser1

これらのイベントは常にpostAppForeground よりも優先

postLaunch、launchError2

されます。たとえば、アプリケーションをバックグラウンドに送信してからログイン中にフォアグラウンドに戻した場合、ログインに成功すると postLaunch が起動されますが、postAppForeground

は起動されません。

その他すべてのイベントは、ランクが最も低いこのイベントに取って代わることができます。

postAppForeground3

SalesforceSDKManager プロパティアプリケーションの起動時の動作を設定するには、AppDelegateの initメソッドで SalesforceSDKManager

プロパティを設定します。これらのプロパティには、アプリケーションの次のような起動設定が含まれています。• 接続アプリケーション識別子• 必要な OAuth 範囲• 認証動作および関連付けられたカスタマイズ少なくとも接続アプリケーションと OAuth 範囲設定を指定する必要があります。SalesforceSDKManagerプロパティは、起動イベントのハンドラブロックの定義にも使用します。イベントハンドラのプロパティは省略可能です。このプロパティを定義しない場合、イベントの発生時にアプリケーションのログに実行時警告が記録されます。通常は、アプリケーションフローを詳細に制御できるようにするため、これらのブロックを実装することをお勧めします。もう 1 つの特に便利なプロパティは、省略可能な authenticateAtLaunchです。アプリケーションの実行が開始されてから特定の時点まで Salesforce 認証を延期するには、このプロパティを NO に設定します。authenticate メッセージを SalesforceSDKManager に送信することで、認証プロセスを任意の時点で実行できます。ただし、常に AppDelegate の init メソッドで起動プロパティを設定し、application:didFinishLaunchingWithOptions: メソッドで launch メッセージをSalesforceSDKManager に送信します。

57

SalesforceSDKManager および SmartStoreSDKManager クラス

ネイティブ iOS の開発

次の表は、SalesforceSDKManager プロパティについて説明したものです。

表 5 : SalesforceSDKManager プロパティ説明プロパティ

(必須) 関連付けられた Salesforce 接続アプリケーションのコンシューマ ID。

connectedAppId

(必須) 関連付けられた Salesforce 接続アプリケーションのコールバック URI。

connectedAppCallbackUri

(必須) アプリケーションに必要な OAuth 範囲。authScopes

(必須) 起動の完了後アプリケーションが機能を再開する方法を制御します。

postLaunchAction

(省略可能) YES (デフォルト) に設定した場合、SalesforceSDKManagerは起動時に認証を試行しま

authenticateAtLaunch

す。この値を NO に設定すると、認証はアプリケーションの別のフェーズに延期されます。適切な時点で、authenticate メッセージをSalesforceSDKManagerに送信して認証を開始します。

(省略可能) 定義した場合、このブロックは起動プロセス中に発生したすべてのエラーに応答します。

launchErrorAction

(省略可能) 定義した場合、このブロックは現在のユーザがログアウトしたときに実行されます。

postLogoutAction

(省略可能) 定義した場合、このブロックは現在のユーザから既存のユーザまたは新規ユーザへの切り替えを処理します。

switchUserAction

メモ: アプリケーションがユーザの切り替えをサポートしている場合、このプロパティは必須です。

(省略可能) 定義した場合、このブロックは Mobile SDK

がフォアグラウンド後のタスクを完了した後に実行されます。

postAppForegroundAction

(省略可能) アプリケーションがバックグラウンドで実行されているときにスナップショットビューを使用す

useSnapshotView

るには、YES に設定します。このビューにより、ユーザがホーム画面からバックグラウンドアプリケーションを参照したときに表示されるアプリケーションのプレビュー画面で、機密コンテンツが覆い隠されます。デフォルトは YES です。

58

SalesforceSDKManager および SmartStoreSDKManager クラス

ネイティブ iOS の開発

説明プロパティ

(省略可能) アプリケーションがバックグラウンドで実行されているときに、ホーム画面から参照されるアプ

snapshotView

リケーションの機密コンテンツを覆い隠すビューを指定します。デフォルトのビューは、白の不透明な画面です。

(省略可能) 異なるパスコードプロバイダを設定し、異なるパスコード暗号化スキームを使用できます。デフォルトは Mobile SDK PBKDF2 プロバイダです。

preferredPasscodeProvider

AppDelegate クラスAppDelegate クラスは、iOS アプリケーションの実際のエントリポイントです。Mobile SDK アプリケーションでは、AppDelegate によって標準の iOS UIApplicationDelegate インターフェースが実装されます。このクラスは、共有 SalesforceSDKManager オブジェクトを使用して Mobile SDK を初期化し、アプリケーションの起動フローを監視します。OAuth 機能は、独立したモジュールに保存されています。この分離によって、Salesforce 認証のオンデマンドでの使用が可能になります。ログインプロセスは、AppDelegate の実装内から開始することも、実際に必要になるまで (サブビューから OAuth をコールするなど) 延期することもできます。

設定AppDelegateテンプレートをカスタマイズするには、まず次の静的変数を Force.com 接続アプリケーションの値に再設定します。• RemoteAccessConsumerKey

static NSString * const RemoteAccessConsumerKey =@"3MVG9Iu66FKeHhINkB1l7xt7kR8...YFDUpqRWcoQ2.dBv_a1Dyu5xa";

この変数は、接続アプリケーションのコンシューマ鍵に対応します。• OAuthRedirectURI

static NSString * const OAuthRedirectURI = @"testsfdc:///mobilesdk/detect/oauth/done";

この変数は、接続アプリケーションのコールバック URL に対応します。

初期化次に、テンプレートアプリケーションで実装される init メソッドを示します。この後に、application:didFinishLaunchingWithOptions:メソッドで SalesforceSDKManagerの launchメソッドへのコールが続きます。- (id)init{

self = [super init];

59

AppDelegate クラスネイティブ iOS の開発

if (self) {[SalesforceSDKManager sharedManager].connectedAppId =

RemoteAccessConsumerKey;[SalesforceSDKManager sharedManager].

connectedAppCallbackUri = OAuthRedirectURI;[SalesforceSDKManager sharedManager].authScopes =

@[ @”web”, @”api” ];__weak AppDelegate *weakSelf = self;[SalesforceSDKManager sharedManager].postLaunchAction =

^(SFSDKLaunchAction launchActionList) {[weakSelf log:SFLogLevelInfo

format:@"Post-launch: launch actions taken: %@",[SalesforceSDKManager

launchActionsStringRepresentation:launchActionList]];

[weakSelf setupRootViewController];};[SalesforceSDKManager sharedManager].launchErrorAction =

^(NSError *error, SFSDKLaunchAction launchActionList) {[weakSelf log:SFLogLevelError

format:@"Error during SDK launch: %@",[error localizedDescription]];

[weakSelf initializeAppViewState];[[SalesforceSDKManager sharedManager] launch];

};[SalesforceSDKManager sharedManager].postLogoutAction = ^{

[weakSelf handleSdkManagerLogout];};[SalesforceSDKManager sharedManager].switchUserAction =

^(SFUserAccount *fromUser, SFUserAccount *toUser) {[weakSelf handleUserSwitch:fromUser toUser:toUser];

};return self;

}

- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{[[SalesforceSDKManager sharedManager] launch];

}

init メソッドで、SalesforceSDKManager オブジェクトは次のことを行います。• SalesforceSDKManager共有インスタンスを使用して、接続アプリケーション識別子や OAuth 範囲などの

設定項目を初期化する。次に例を示します。[SalesforceSDKManager sharedManager].connectedAppId =

RemoteAccessConsumerKey;[SalesforceSDKManager sharedManager].connectedAppCallbackUri =

OAuthRedirectURI;[SalesforceSDKManager sharedManager].authScopes =

@[ @"web", @"api" ];

• postLaunchAction、launchErrorAction、postLogoutAction、switchUserActionイベントを処理するプロパティにコードブロックを割り当てる。ブロックの実装で weak self が使用されていることに注意

60

AppDelegate クラスネイティブ iOS の開発

してください。サイクルに対してコードを保護することに加え、この使用例は SalesforceSDKManager

が単なるマネージャであるという重要な点を示しています。つまり、永続的な self を必要とする実際の処理はすべて、作業を実際に実行する代理メソッド内で行われます。次の表に、AppDelegateテンプレートによる各イベントの処理方法をまとめます。

デフォルトの動作Delegate メソッドイベント

アプリケーションのルートビューコントローラをインスタンス化

setupRootViewControllerpostLaunch

し、それを AppDelegate のwindow.rootViewController

プロパティに割り当てます。

ルートビューコントローラを初期ビューコントローラにリセットします。

initializeAppViewStatelaunchError

有効なユーザアカウントが複数ある場合、以前に認証されたアカウ

handleSdkManagerLogoutpostLogout

ントをユーザが選択できるようにするため、ルートビューコントローラをマルチユーザビューコントローラに変更します。有効なアカウントが 1 つしかない場合は、そのアカウントに自動的に切り替えられます。有効なアカウントがない場合は、ログイン画面が表示されます。

ルートビューコントローラを初期ビューコントローラにリセット

handleUserSwitch:toUser:switchUser

し、起動フローを再度開始します。

このプロセスのどの部分もカスタマイズできます。少なくとも、認証後に独自のコントローラが表示されるように setupRootViewControllerを変更してください。また、initializeAppViewStateをカスタマイズして独自の起動ページを表示したり、ニーズに合わせて InitialViewController をカスタマイズすることもできます。さらに、アプリケーションにとって最も適切な場所に認証の詳細を移動することもできます。 Mobile SDK では、アクションの実行時期 (または実行するかどうか) は規定されませんが、標準の iOS 規則は適用されます。たとえば、self.windowには、application:didFinishLaunchingWithOptions:が完了するまでに rootViewController が必要です。

UIApplication イベントハンドラアプリケーションの代理クラスを使用して、UIApplicationイベントハンドラを実装することもできます。実装またはカスタマイズを考慮すべき重要なイベントハンドラは、次のとおりです。

61

AppDelegate クラスネイティブ iOS の開発

application:didFinishLaunchingWithOptions:

アプリケーションの起動時の最初のエントリポイントです。プロセスが最初に開始したとき (バックグラウンド/フォアグラウンドサイクルの後ではない) にのみコールされます。テンプレートアプリケーションでは、次の処理を行うためにこのメソッドが使用されます。• window プロパティを初期化する• ルートビューコントローラを初期ビューコントローラに設定する (initializeAppViewState を参照)

• 初期ウィンドウを表示する• 起動メッセージを共有 SalesforceSDKManagerインスタンスに送信することにより、認証を開始する

applicationDidBecomeActive

アプリケーションがフォアグラウンドになるたびにコールされます。iOS SDK にはデフォルトの親動作はありませんが、それを使用する場合は下から順に実装する必要があります。

application:didRegisterForRemoteNotificationsWithDeviceToken:、application:didFailToRegisterForRemoteNotificationsWithError:

Salesforce からの受信転送通知の処理に使用されます。すべての UIApplicationイベントハンドラのリストは、「iOS Developer Library」の「UIApplicationDelegate Protocol

Reference」を参照してください。

遅延ログインについてユーザログインの認証を、postLaunchイベント発生後の任意の論理ポイントに延期することができます。認証を延期する手順は、次のとおりです。1. AppDelegate クラスの init メソッドで、SalesforceSDKManager の authenticateAtLaunch プロパ

ティを NO に設定します。2. launch メソッドを SalesforceSDKManager に送信します。3. SFAuthenticationManager の loginWithCompletion:failure: メソッドを遅延ログインポイントで

コールします。認証を延期する場合、ログインの完了および失敗を処理するロジックは、アプリケーションによって判断されます。

既存のアプリケーションのアップグレードMobile SDK 2.3 以前からアプリケーションをアップグレードする場合、起動イベントを処理するカスタムコードはすべて再利用できますが、若干異なるコンテキストに移動する必要があります。たとえば、SFAuthenticationManagerDelegate の authManagerDidLogout: メソッドを実装した以前のコードは、SalesforceSDKManager の postLogoutAction ブロックに移動します。同様に、SFUserAccountManagerDelegate の useraccountManager:didSwitchFromUser:toUser: を実装したコードは、SalesforceSDKManager の switchUserAction ブロックに含まれます。最後に、AppDelegate の実装で、SFAuthenticationManager の loginWithCompletion:failure: メソッドへのすべてのコールを、SalesforceSDKManagerの launchメソッドに置き換えます。完了ブロック

62

AppDelegate クラスネイティブ iOS の開発

のコードを postLaunchActionプロパティに移動し、失敗ブロックのコードを launchErrorActionプロパティに移動します。

関連トピック:

iOS での転送通知の使用

ビューコントローラについてAppDelegate クラスに記載されているビューおよびビューコントローラに加え、Mobile SDK ではSFAuthorizingViewControllerクラスが公開されます。このコントローラでは、必要に応じてログイン画面が表示されます。ログイン画面の表示をカスタマイズする手順は、次のとおりです。1. カスタム表示ロジックを実装するように SFAuthorizingViewController クラスを上書きします。2. カスタマイズしたクラスのインスタンスに [SFAuthenticationManager

sharedManager].authViewController プロパティを設定します。アプリケーションで最も重要なビューコントローラは、ログイン後または (ログインが延期されている場合は)

起動後に表示される最初の画面を管理するビューコントローラです。このコントローラはアプリケーションで行われる他のすべてのものを制御するため、ルートビューコントローラと呼ばれます。iOS プロジェクトテンプレートの Mobile SDK には、最低限必要な実装を示す RootViewController という名前の骨格のみのクラスが備えられています。アプリケーションで追加のビューコントローラが必要な場合は、必要に応じて自由に作成できます。Mobile SDK

プロジェクトで使用されるビューコントローラには、いくつかのオプションが可能です。たとえば、Mobile SDK

iOS テンプレートプロジェクトは UITableViewControllerインターフェースのルートビュークラスを基にしていますが、RestAPIExplorer サンプルプロジェクトでは UIViewController インターフェースが使用されます。iOS 自体および Objective-C 言語によってのみ、技術的な制限が加えられます。

RootViewController クラスRootViewController クラスは、テンプレートプロジェクトおよびそこから生成されるプロジェクトの一部としてのみ存在します。このクラスでは、アプリケーションが Salesforce REST API とやり取りするためのフレームワークを設定する SFRestDelegate プロトコルが実装されます。ルートビューコントローラの定義方法に関係なく、SFRestDelegateを使用して REST API 経由で Salesforce データにアクセスする場合は、SFRestDelegate

を実装する必要があります。

RootViewController のデザインMobile SDKを使用して作成される非常に基本的なアプリケーションの要素として、RootViewControllerクラスでは重要項目のみが取り扱われます。主要な 2 つのタスクは次のとおりです。• Salesforce REST API を使用して Salesforce データをクエリする• Salesforce データをテーブルに表示する

63

ビューコントローラについてネイティブ iOS の開発

以上の操作を行うため、このクラスは UITableViewControllerを継承して、SFRestDelegateプロトコルを実装します。このアクションは、UIViewController:viewDidLoad メソッドの上書きで開始します。- (void)viewDidLoad{

[super viewDidLoad];self.title = @"Mobile SDK Sample App";

// Here we use a query that should work on either// Force.com or Database.comSFRestRequest *request =

[[SFRestAPI sharedInstance]requestForQuery:@"SELECT Name FROM User LIMIT 10"];

[[SFRestAPI sharedInstance] send:request delegate:self];}

ビューがメモリに初めて読み込まれると、iOS ランタイムにより viewDidLoad がビューのライフサイクルで1 回のみコールされます。この骨格のみのアプリケーションの目的は、アプリケーションで定義済みの唯一のビューに 1 セットのデータのみを読み込むことにあります。他のビューを作成するには、別の場所でクエリを実行する必要がある場合もあります。たとえば、ルートビューに表示されるデータをユーザが編集できる詳細ビューを追加する場合は、ルートビューに値が再表示されるときに値を更新します。この場合、viewWillAppear など、より適切なメソッドでクエリを実行できます。スーパークラスメソッドをコールすると、ビューのタイトルが設定され、非同期の SOQL クエリの形式で REST

要求が発行されます。この場合のクエリは、各 User オブジェクトから Name プロパティを取得する単純なSELECT ステートメントで、返される行は 10 行に制限されます。requestForQuery および send:delegate:

メッセージが、SFRestAPI クラスの単一の共有インスタンスに送信されます。この単一オブジェクトをすべての REST 要求に使用します。このオブジェクトでは、単一の SFAccountManagerオブジェクトの認証済みログイン情報を使用して、認証済み要求の作成と送信が行われます。Salesforce REST API は、送信メッセージに示される代理オブジェクトに状況メッセージとデータ (可能な場合) を渡すことによって応答します。この場合、RootViewController 自体が代理オブジェクトになります。[[SFRestAPI sharedInstance] send:request delegate:self];

RootViewController オブジェクトは、SFRestDelegate プロトコルを実装するため、SFRestAPI の代理オブジェクトとしての役割を果たすことができます。このプロトコルでは、4 つの可能な応答コールバックが宣言されます。• request:didLoadResponse: — 要求は処理されました。代理オブジェクトは JSON 形式の応答を受信しま

す。成功を示すコールバックはこれだけです。• request:didFailLoadWithError: — 要求を処理できませんでした。代理オブジェクトはエラーメッセー

ジを受信します。• requestDidCancelLoad — システム管理者による操作、ネットワーク障害、他の予期しないイベントな

ど、外部要因により要求がキャンセルされました。代理オブジェクトは戻り値を受信しません。• requestDidTimeout — Salesforce サーバが時間内に応答しませんでした。代理オブジェクトは戻り値を受

信しません。

64

RootViewController クラスネイティブ iOS の開発

応答は、RootViewController で実装したいずれかのコールバックで受信されます。Salesforce データを処理するコードを request:didLoadResponse: コールバックに配置します。次に例を示します。- (void)request:(SFRestRequest *)request

didLoadResponse:(id)jsonResponse {NSArray *records = [jsonResponse objectForKey:@"records"];NSLog(@"request:didLoadResponse: #records: %d", records.count);self.dataRows = records;[self.tableView reloadData];

}

idデータ型の使用で提示されるように、このコードでは JSON 応答が汎用的な Objective-C 形式で処理されます。jsonResponse オブジェクトは NSDictionary のインスタンスとして処理され、そのレコードは NSArray

オブジェクトとして扱われます。RootViewControllerでは UITableViewControllerが実装されるため、抽出されたレコードを使用してテーブルを入力するのは簡単です。次のいずれかの条件で、request:didFailLoadWithError: がコールされます。• 無効な要求パラメータを使用すると、kSFRestErrorDomain エラーコードが返されます。たとえば、

requestForQuery: に nil を渡したり、存在しないオブジェクトを更新しようとすると、このエラーが返されます。

• OAuth アクセストークンが期限切れになると、フレームワークで新しいアクセストークンを取得しようとし、成功するとクエリが再試行されます。新しいアクセストークンまたはセッション ID の要求に失敗すると、kSFOAuthErrorDomainエラーコードが返されます。たとえば、アクセストークンが期限切れであり、OAuth 更新トークンが無効な場合に、このエラーが返されます。このような状況になることはまずありません。

• 低レベルの HTTP 要求に失敗すると、RKRestKitErrorDomain エラーコードが返されます。たとえば、Salesforce サーバが一時的にアクセスできない場合に、このエラーが返されます。

他のコールバックは自己説明的であり、エラーコードは返されません。エラーメッセージの表示、ログへの書き込み、要求の再試行など、結果の処理方法を自由に選択できます。

Salesforce REST API についてSalesforce Mobile SDK を使用したネイティブアプリケーションの開発は、Salesforce REST API の使用が中心になっています。Salesforce では、REST パラメータを指定した URI で広範囲にわたるオブジェクトベースのタスクを使用できます。Mobile SDK では、要求を書式設定する低レベルのほとんどの作業を処理するインターフェースで、これらの HTTP コールがラップされます。Mobile SDK for iOS では、すべての REST 要求が非同期に実行されます。REST ラッパークラスの代理バージョンまたはブロックバージョンを選択して、要求をさまざまなシナリオに適用できます。REST 応答は、要求に成功した場合は NSArray または NSDictionary オブジェクトとして書式設定され、要求に失敗した場合は NSError

オブジェクトとして書式設定されます。Salesforce REST の応答形式についての詳細は、『Force.com REST API 開発者ガイド』を参照してください。

関連トピック:

iOS のネイティブ REST API クラス

65

Salesforce REST API についてネイティブ iOS の開発

サポートされている操作iOS REST API は、Salesforce REST および SOAP API で提供される標準のオブジェクト操作をサポートしています。Salesforce Mobile SDKには、その REST 要求 API の代理バージョンとブロックバージョンが備えられています。代理要求メソッドは SFRestAPI クラスで定義されますが、ブロック要求メソッドは SFRestAPI (Blocks) カテゴリで定義されます。ファイル要求は、SFRestAPI (Files) カテゴリで定義されます。「SFRestAPI

(Files) カテゴリ」を参照してください。サポートされる操作は次のとおりです。

Block メソッドDelegate メソッド操作

sendRESTRequest:failBlock:

completeBlock:

send:delegate:Manual REST request

ユーザが作成した要求を実行する

performSOQLQuery:failBlock:

completeBlock:

requestForQuery:SOQL query

特定の SOQL 文字列を実行し、結果のデータセットを返す

performSOSLSearch:failBlock:

completeBlock:

requestForSearch:SOSL search

特定の SOSL 文字列を実行し、結果のデータセットを返す

performRequestForSearchResultLayout:failBlock:

completeBlock:

requestForSearchResultLayout:Search Result Layout

検索結果レイアウトを取得する要求を実行する

performRequestForSearchScope-AndOrderWithFailBlock:

requestForSearchScopeAndOrderSearch Scope andOrder

failBlock:completeBlock:

検索範囲と検索順序を取得する要求を実行する

performMetadataWithObjectType:failBlock:

completeBlock:

requestForMetadataWith-ObjectType:

Metadata

66

Salesforce REST API についてネイティブ iOS の開発

Block メソッドDelegate メソッド操作

オブジェクトのメタデータを返す

performDescribeGlobalWithFailBlock:completeBlock:

requestForDescribeGlobalDescribe global

組織で使用できるすべてのオブジェクトとそのメタデータのリストを返す

performDescribeWithObjectType:failBlock:

completeBlock:

requestForDescribe-

WithObjectType:

Describe with objecttype

1 つのオブジェクト種別の説明を返す

performRetrieveWithObjectType:objectId:

requestForRetrieve-Retrieve

オブジェクト ID 別に単一レコードを取得する

fieldList:failBlock:completeBlock:

WithObjectType:

objectId:

fieldList:

performUpdateWithObjectType:objectId:

requestForUpdate-WithObjectType:

Update

指定された対応付けでオブジェクトを更新する

fields:failBlock:

completeBlock:objectId:

fields:

performUpsertWithObjectType:externalIdField:

requestForUpsert-WithObjectType:

Upsert

外部 ID が外部 ID 項目に現在存在してい externalId:

fields:externalIdField:るかどうかに基づい failBlock:

completeBlock:externalId:

67

Salesforce REST API についてネイティブ iOS の開発

Block メソッドDelegate メソッド操作

fields:て、外部データからオブジェクトを更新または挿入する

performCreateWithObjectType:fields:

requestForCreateWithObjectType:

fields:

Create

指定したオブジェクトに新しいレコードを作成する

failBlock:completeBlock:

performDeleteWithObjectType:objectId:

requestForDeleteWithObjectType:

objectId:

Delete

指定された ID を持つ特定のタイプのオブジェクトを削除する

failBlock:completeBlock:

performRequestForVersions-WithFailBlock:completeBlock:

requestForVersionsVersions

Salesforce バージョンのメタデータを返す

performRequestForResources-WithFailBlock:completeBlock:

requestForResourcesResources

リソース名およびURI を含む、指定された API バージョンで使用可能なリソースを返す

SFRestAPI インターフェースSFRestAPI は、Salesforce REST 要求を作成および書式設定するためのネイティブインターフェースを定義します。これは、要求を書式設定し、Salesforce サービスに送信してから、SFRestDelegate プロトコルの実装エントリに非同期応答をリレーすることによって動作します。SFRestAPIは、SFRestRequestインスタンスのファクトリとしての役割を果たし、Salesforce REST API でサポートされる要求種別を表すメソッドグループを定義します。各 SFRestAPI メソッドは、1 つの要求種別に対応します。各メソッドでは、要求が SFRestRequestインスタンス形式で返されます。その戻り値を使用して、要求を Salesforce サーバに送信します。HTTP コーディングレイヤはカプセル化されるため、REST API 構文を考慮する必要はありません。サポートされるクエリファクトリメソッドのリストについては、「サポートされている操作」を参照してください。

68

Salesforce REST API についてネイティブ iOS の開発

SFRestDelegate プロトコルクラスで SFRestDelegate プロトコルが採用されると、Salesforce サーバから送信される REST 応答のターゲットとなります。REST 要求をサーバに送信するときに、応答を受信するオブジェクトを共有 SFRestAPI インスタンスに示します。サーバから応答が送信されると、Mobile SDK によって、指定されたオブジェクトの適切なプロトコルメソッドに応答が転送されます。SFRestDelegate プロトコルでは、4 つの可能な応答が宣言されます。• request:didLoadResponse: — 要求は処理されました。代理オブジェクトは JSON 形式の応答を受信しま

す。成功を示すコールバックはこれだけです。• request:didFailLoadWithError: — 要求を処理できませんでした。代理オブジェクトはエラーメッセー

ジを受信します。• requestDidCancelLoad — システム管理者による操作、ネットワーク障害、他の予期しないイベントな

ど、外部要因により要求がキャンセルされました。代理オブジェクトは戻り値を受信しません。• requestDidTimeout — Salesforce サーバが時間内に応答しませんでした。代理オブジェクトは戻り値を受

信しません。応答は、いずれかの代理メソッドの実装環境で受信されます。応答種別は予測できないため、すべてのメソッドを実装する必要があります。

request:didLoadResponse: メソッドrequest:didLoadResponse: メソッドは、成功条件を処理する唯一のプロトコルメソッドであるため、Salesforce データを処理するコードをこのメソッドに含めます。次に例を示します。- (void)request:(SFRestRequest *)request

didLoadResponse:(id)jsonResponse {NSArray *records = [jsonResponse objectForKey:@"records"];NSLog(@"request:didLoadResponse: #records: %d", records.count);self.dataRows = records;[self.tableView reloadData];

}

サーバでは、すべての応答が JSON 文字列として作成されます。Mobile SDKでは、このような未加工の応答を受信し、iOS SDK オブジェクトとして再度書式設定してから、request:didLoadResponse: メソッドに渡します。このため、jsonResponseペイロードは、NSDictionaryオブジェクトまたは NSArrayオブジェクトとして受信されます。オブジェクト種別は、返される JSON データのデータ型によって異なります。サーバ応答の最上位レベルが JSON オブジェクトを表している場合、jsonResponse は NSDictionary オブジェクトです。最上位レベルが他のデータの JSON 配列を表している場合、jsonResponse は NSArray オブジェクトです。要求のデータ型をメソッドで推測できない場合は、[NSObject isKindOfClass:] を使用してデータ型を判断します。次に例を示します。if ([jsonResponse isKindOfClass:[NSArray class]]) {

// Handle an NSArray here.} else {

// Handle an NSDictionary here.}

69

Salesforce REST API についてネイティブ iOS の開発

応答を NSDictionary オブジェクトとして指定し、そのレコードを NSArray オブジェクトに抽出することができます。これを行うには、キー「records」を使用して NSDictionary:objectForKey: メッセージを送信します。

request:didFailLoadWithError: メソッド次のいずれかの条件で、request:didFailLoadWithError: コールバックがコールされます。• 無効な要求パラメータを使用すると、kSFRestErrorDomain エラーコードが返されます。例:

requestForQuery: に nil を渡したり、存在しないオブジェクトを更新しようとした。• OAuth アクセストークンが期限切れになると、フレームワークで新しいアクセストークンを取得しようと

し、成功するとクエリが再試行されます。新しいアクセストークンまたはセッション ID の要求に失敗すると、kSFOAuthErrorDomain エラーコードが返されます。例: アクセストークンが期限切れであり、OAuth

更新トークンが無効である。このような状況になることはまずありません。• 低レベルの HTTP 要求に失敗すると、RKRestKitErrorDomain エラーコードが返されます。例: Salesforce

サーバが一時的にアクセスできなくなる。

requestDidCancelLoad および requestDidTimeout メソッドrequestDidCancelLoadおよび requestDidTimeout代理メソッドは自己説明的であり、エラーコードは返されません。エラーメッセージの表示、ログへの書き込み、要求の再試行など、結果の処理方法を自由に選択できます。

REST 要求の作成Salesforce Mobile SDK for iOS では、多くの種類の SOQL 要求と SOSL REST 要求がネイティブでサポートされます。SFRestAPI クラスには、構文に関する詳細のほとんどを処理するファクトリメソッドが備えられています。また、Mobile SDK では、REST 要求をかなり柔軟に作成することもできます。• 標準の SOQL クエリおよび SOSL 検索の場合、SFRestAPI メソッドにより、最小限のデータ入力に基づいて

クエリ文字列が作成され、Salesforce サーバに送信可能な SFRestRequest オブジェクトにクエリ文字列がパッケージ化されます。

• SOQL または SOSL に基づいていない Salesforce REST API を使用している場合は、SFRestRequestメソッドで、API 形式と一致する要求そのものを設定できます。

• SFRestAPI (QueryBuilder) カテゴリには、自由形式の SOQL クエリ文字列や SOSL 検索文字列を作成するメソッドが備えられているため、クエリ文字列または検索文字列を手動で書式設定する必要はありません。

• SFRestAPI (Blocks)カテゴリの要求メソッドでは、代理オブジェクトを使用する代わりに、コールバックコードをブロックメソッドとして渡すことができます。

REST 要求の送信Salesforce Mobile SDK for iOS では、多くの種類の SOQL 要求と SOSL REST 要求がネイティブでサポートされます。SFRestAPI には、構文に関する詳細のほとんどを処理するファクトリメソッドが備えられています。

70

Salesforce REST API についてネイティブ iOS の開発

Mobile SDK は、実行時に SFRestAPI の単一インスタンスを作成します。このインスタンスを使用して、SFRestRequest オブジェクトを取得し、そのオブジェクトを Salesforce サーバに送信します。REST 要求を SFRestAPI 代理オブジェクトから Salesforce サーバに送信する手順は、次のとおりです。1. SOQL、SOSL、または他の REST の要求文字列を作成します。

標準の SOQL クエリおよび SOSL クエリの場合、最も便利で信頼できる方法は、SFRestAPI クラスのファクトリメソッドを使用することです。「サポートされている操作」を参照してください。

2. 要求文字列を使用して、SFRestRequest オブジェクトを作成します。ニーズに合った要求ファクトリメソッドを使用して、SFRestAPIの単一インスタンスにメッセージを送信します。たとえば、次のコードでは、SOQL クエリを準備する SFRestAPI:requestForQuery: メソッドを使用しています。// Send a request factory message to the singleton SFRestAPI instanceSFRestRequest *request = [[SFRestAPI sharedInstance]

requestForQuery:@"SELECT Name FROM User LIMIT 10"];

3. send:delegate: メッセージを共有 SFRestAPI インスタンスに送信します。新しい SFRestRequest オブジェクトを send: パラメータとして使用します。2 つ目のパラメータは、サーバ応答を受信するSFRestDelegate オブジェクトを指定します。次の例では、クラス自体で SFRestDelegate プロトコルが実装されるため、delegate: が self に設定されます。// Use the singleton SFRestAPI instance to send the// request, specifying this class as the delegate.[[SFRestAPI sharedInstance] send:request delegate:self];

SFRestRequest クラスSalesforce Mobile SDK には、アプリケーションに便利なクラスとして SFRestRequest インターフェースがあります。SFRestAPI には、入力内容から要求を作成する要求メソッドが備えられています。この要求は、SFRestRequestインスタンスとしてパッケージ化され、アプリケーションに返されます。ほとんどの場合、SFRestRequest オブジェクトを操作する必要はありません。通常、変更を加えずにそのままSFRestAPI:send:delegate: メソッドに渡すだけで十分です。Chatter REST API を使用するなど、Mobile SDKで直接サポートされない REST 要求を送信する場合は、SFRestRequest

オブジェクトを手動で作成および設定できます。

SFRestRequest メソッドの使用SFRestAPIツールは、SOQL および SOSL ステートメントをネイティブでサポートしており、文法を理解し、アプリケーションからの最小限の入力に基づいて有効な要求を書式設定することができます。ただし、Salesforce

には、SOQL クエリや SOSL 検索とは関係ない製品固有の REST API も一部含まれています。このような要求にもMobile SDK リソースを使用して、設定と送信を行うことができます。この処理は、SOQL クエリ要求の送信と類似しています。主な違いは、SFRestAPI メソッドに依存するのではなく、SFRestRequest オブジェクトの作成と入力を直接行うことにあります。Mobile SDK を使用して非 SOQL および非 SOSL REST の要求を送信する手順は、次のとおりです。1. SFRestRequest のインスタンスを作成します。

71

Salesforce REST API についてネイティブ iOS の開発

2. SFRestRequest オブジェクトで、必要なプロパティを設定します。3. SFRestAPI の単一インスタンスで send:delegate: をコールし、作成した SFRestRequest オブジェク

トを最初のパラメータとして渡します。次の例は、GET 操作を実行して、特定の Chatter フィードにすべての項目を取得します。SFRestRequest *request = [[SFRestRequest alloc] init];[request setDelegate:self];[request setEndpoint:kSFDefaultRestEndpoint];[request setMethod:SFRestMethodGET];[request setPath:

[NSString stringWithFormat:@"/v26.0/chatter/feeds/record/%@/feed-items",recordId]];

[[SFRestAPI sharedInstance] send:request delegate:self];

4. また、requestWithMethod:path:queryParams クラスメソッドを使用して、同じ要求を作成することもできます。SFRestRequest *request =

[SFRestRequestrequestWithMethod:SFRestMethodGET

path:[NSString

stringWithFormat:@"/v26.0/chatter/feeds/record/%@/feed-items",

recordId]queryParams:nil];

[[SFRestAPI sharedInstance] send:request delegate:self];

5. パラメータのある要求を実行するには、パラメータ文字列を作成してから、SFJsonUtils:objectFromJSONString静的メソッドを使用して NSDictionaryオブジェクトでパラメータ文字列をラップします (必要に応じて、NSDictionary オブジェクトをインラインで作成するのではなく、メソッドコールの前に直接作成してもかまいません)。次の例は、Chatter フィードにコメントを追加する POST 操作を実行します。NSString *body =

[NSString stringWithFormat:@"{ \"body\" :

{\"messageSegments\" :[{ \"type\" : \"Text\",

\"text\" : \"%@\"}]}

}",comment];

SFRestRequest *request =[SFRestRequestrequestWithMethod:SFRestMethodPOST

path:[NSStringstringWithFormat:@"/v26.0/chatter/feeds/record/%@/feed-items",

72

Salesforce REST API についてネイティブ iOS の開発

recordId]queryParams:

(NSDictionary *)[SFJsonUtils objectFromJSONString:body]];

[[SFRestAPI sharedInstance] send:request delegate:self];

6. 要求の HTTP ヘッダーを設定するには、setHeaderValue:forHeaderNameメソッドを使用します。このメソッドは、HTML 表示用に事前にエンコードされている Chatter フィードを表示する場合に役立ちます。ネイティブアプリケーションの Chatter コメントに不要なエスケープシーケンスが表示されている場合、要求を送信する前に次のように X-Chatter-Entity-Encoding ヘッダーを「false」に設定します。...[request setHeaderValue:@"false" forHeaderName:@"X-Chatter-Entity-Encoding"];[[SFRestAPI sharedInstance] send:request delegate:self];

認証されていない REST 要求特定のケースでは、ユーザが認証される前に一部のアプリケーションで REST コールを実行する必要があります。その他のケースでは、アプリケーションで、Salesforce認証を必要としないSalesforce外のサービスにアクセスする必要があります。認証トークンを要求しないように SFRestRequest インスタンスを設定するには、requiresAuthentication プロパティを NO に設定します。

メモ: 認証されていない REST 要求では、フルパスの URL が必要です。Mobile SDK では、認証されていないエンドポイントの先頭にインスタンス URL は追加されません。

例:

SFRestRequest *request = [[SFRestAPI sharedInstance] requestForVersions];request.requiresAuthentication = NO;

SFRestAPI (Blocks) カテゴリ必要に応じて、代理オブジェクトの代わりにブロックを使用してコールバックコードを実行できます。ネイティブ iOS の Salesforce Mobile SDK には、SFRestAPI 要求メソッドごとに付随ブロックがあります。これらのメソッドは、SFRestAPI (Blocks) カテゴリで定義されます。ブロック要求メソッドは、代理要求メソッドに酷似しています。どのメソッドからも、SFRestRequestを指すポインタが返され、同じパラメータを必要とします。ブロック要求メソッドは、次の点で代理要求メソッドと異なります。1. REST API パラメータのコピーに加え、各メソッドには、予期される応答データに応じて、SFRestFailBlock

タイプの失敗ブロックと、SFRestDictionaryResponseBlockタイプまたは SFRestArrayResponseBlock

タイプの完了ブロックの 2 つのブロックが必要です。2. ブロックベースのメソッドから要求が送信されるため、別個の送信メソッドをコールする必要はありませ

ん。要求に失敗した場合は、SFRestRequest * 戻り値を使用して要求を再試行できます。これを行うには、SFRestAPI:sendRESTRequest:failBlock:completeBlock: メソッドを使用します。

ブロックおよび代理メソッドを適切に使用することで、アプリケーションの読みやすさを調整し、メンテナンスを簡単にするのに役立ちます。ブロックの使用に最適な条件は、C++ でのインライン関数や Java での匿名関

73

Salesforce REST API についてネイティブ iOS の開発

数を要求する条件と一致することがよくあります。ただし、これはあくまでも一般的な目安です。最終的には。アプリケーションの実際の動作を調べたうえで判断する必要があります。

SFRestAPI (QueryBuilder) カテゴリSOQL クエリまたは SOSL 検索の正しい構文が明確でない場合は、SFRestAPI (QueryBuilder)カテゴリメソッドを利用できます。これらのメソッドでは、指定した基本条件からクエリ文字列が作成され、書式設定された文字列が返されます。返された値を次のいずれかの SFRestAPI メソッドに渡すことができます。• – (SFRestRequest *)requestForQuery:(NSString *)soql;

• – (SFRestRequest *)requestForSearch:(NSString *)sosl;

SFRestAPI (QueryBuilder) には、SOQL クエリと SOSL 検索にそれぞれ 2 つの静的メソッドがあります。1 つは最小限のパラメータを受け入れ、もう 1 つはすべてのオプションを受け入れます。

SOSL メソッドSOSL クエリビルダーメソッドは、次のとおりです。+ (NSString *) SOSLSearchWithSearchTerm:(NSString *)term

objectScope:(NSDictionary *)objectScope;

+ (NSString *) SOSLSearchWithSearchTerm:(NSString *)termfieldScope:(NSString *)fieldScopeobjectScope:(NSDictionary *)objectScope

limit:(NSInteger)limit;

SOSL 検索メソッドのパラメータは、次のとおりです。• termは、検索文字列です。この文字列には任意の値を指定できます。メソッドでは、検索を処理する前に

SOSL 予約文字がすべてエスケープされます。• fieldScope は、検索する項目を示します。これは、nil またはいずれかの IN 検索グループ式 (「IN ALL

FIELDS」、「IN EMAIL FIELDS」、「IN NAME FIELDS」、「IN PHONE FIELDS」、または「IN SIDEBAR FIELDS」) になります。デフォルトでは nil の値は「IN NAME FIELDS」になります。「Salesforce Object Search Language (SOSL)」を参照してください。

• objectScope は、検索するオブジェクトを指定します。有効な値は次のとおりです。– nil — 範囲に制限はありません。検索可能なすべてのオブジェクトが検索されます。– NSDictionaryオブジェクトポインタ — SOSL RETURNING fieldspec に対応します。各キーは sObject名で

す。各値は、項目リストおよびキーオブジェクトの省略可能な WHERE、ORDER BY、LIMIT 句を含む文字列です。NSDictionaryオブジェクトを使用する場合、各値には少なくとも項目リストが含まれている必要があります。たとえば、ディクショナリエントリで次の SOSL ステートメントを表すとします。FIND {Widget Smith}IN Name FieldsRETURNING Widget__c (name Where createddate = THIS_FISCAL_QUARTER)

74

Salesforce REST API についてネイティブ iOS の開発

この場合は、キーを “Widget__c” に設定し、値を “name WHERE createddate = “THIS_FISCAL_QUARTER” に設定します。次に例を示します。[SFRestAPI

SOSLSearchWithSearchTerm:@"all of these will be escaped:~{]"objectScope:[NSDictionary

dictionaryWithObject:@"name WHEREcreateddate="THIS_FISCAL_QUARTER"forKey:@"Widget__c"]];

– NSNull — 範囲が指定されていません。• limit — 返される結果数を制限するには、このパラメータを、受信する結果の最大数に設定します。

SOQL メソッドSOQL 文字列を作成する SOQL QueryBuilder メソッドは、次のとおりです。+ (NSString *) SOQLQueryWithFields:(NSArray *)fields

sObject:(NSString *)sObjectwhere:(NSString *)wherelimit:(NSInteger)limit;

+ (NSString *) SOQLQueryWithFields:(NSArray *)fieldssObject:(NSString *)sObjectwhere:(NSString *)where

groupBy:(NSArray *)groupByhaving:(NSString *)havingorderBy:(NSArray *)orderBylimit:(NSInteger)limit;

SOQL メソッドのパラメータは、SOQL クエリの構文に対応します。fields と sObject を除くすべてのパラメータは、nil に設定することができます。

説明パラメータ名

クエリする項目名の配列。fields

クエリするオブジェクトの名前。sObject

1 つ以上のクエリ条件を指定する式。where

結果レコードのグループ化に使用する項目名の配列。groupBy

グループ化した結果を絞り込むための式 (通常、集計関数を使用)。groupBy でのみ使用されます。

having

結果レコードの並び替えに使用する項目名の配列。orderBy

返されるレコードの最大数。limit

「SELECT」を参照してください。

75

Salesforce REST API についてネイティブ iOS の開発

SOSL のサニタイズQueryBuilderカテゴリには、SOSL 検索語をクリーンアップするためのクラスメソッドも用意されています。+ (NSString *) sanitizeSOSLSearchTerm:(NSString *)searchTerm;

このメソッドでは、入力文字列に含まれているすべての SOSL 予約文字がエスケープされ、エスケープされたバージョンが返されます。次に例を示します。NSString *soslClean = [SFRestAPI sanitizeSOSLSearchTerm:@"FIND {MyProspect}"];

このコールは、“FIND \{MyProspect\}” を返します。sanitizeSOSLSearchTerm:メソッドは、SOSL および SOQL QueryBuilder メソッドの実装でコールされるため、QueryBuilder メソッドに渡す文字列でこのメソッドをコールする必要はありません。ただし、独自のクエリを手動で作成しているなどの場合は、このメソッドを使用できます。SOSL 予約文字は、次のとおりです。\ ? & | ! { } [ ] ( ) ^ ~ * : " ' + -

SFRestAPI (Files) カテゴリSFRestAPI (Files)カテゴリには、ファイル操作要求を作成するメソッドが備えられています。各メソッドは、新しい SFRestRequest オブジェクトを返します。アプリケーションは、このオブジェクトを Salesforce

サービスに送信して要求を処理します。たとえば、次のコードスニペットはrequestForOwnedFilesList:page: メソッドをコールして SFRestRequest オブジェクトを取得します。次に、そのオブジェクトが所有するオブジェクトを、応答を受信する代理オブジェクトとして指定して、要求オブジェクトをサーバに送信します。SFRestRequest *request = [[SFRestAPI sharedInstance] requestForOwnedFilesList:nil page:0];[[SFRestAPI sharedInstance] send:request delegate:self];

メモ: この例では、最初のパラメータ (userId) に nil を渡します。この値で、コンテキスト (ログインしている) ユーザの ID を使用するように requestForOwnedFilesList:page:メソッドに指示します。pageNum

パラメータに 0 を渡すと、最初のページを取得するようメソッドに指示します。Files 機能およびネットワーキング機能についての詳細は、「ファイルとネットワーキング」を参照してください。

メソッドSFRestAPI (Files)カテゴリでは、以下の操作がサポートされています。このカテゴリの詳細は、「SFRestAPI

(Files) カテゴリ — 要求メソッド (iOS)」を参照してください。REST リクエストボディおよびレスポンスボディについての詳細は、[Chatter REST APIリソース] > [FilesResources] (http://www.salesforce.com/us/developer/docs/chatterapi)

を参照してください。- (SFRestRequest*) requestForOwnedFilesList:(NSString*) userId page:(NSUInteger)page;

指定されたユーザが所有するファイルのリストからページを取得する要求を構築します。- (SFRestRequest*) requestForFilesInUsersGroups: (NSString*)userId page:(NSUInteger)page;

ユーザのグループが所有するファイルのリストからページを取得する要求を構築します。- (SFRestRequest*) requestForFilesSharedWithUser: (NSString*)userId page:(NSUInteger)page;

ユーザと共有しているファイルのリストからページを取得する要求を構築します。

76

Salesforce REST API についてネイティブ iOS の開発

- (SFRestRequest*) requestForFileDetails: (NSString*)sfdcId forVersion:(NSString*)version;

特定のバージョンのファイルの詳細を取得する要求を構築します。- (SFRestRequest*) requestForBatchFileDetails: (NSArray*)sfdcIds;

1 つの要求で 1 つ以上のファイルの最新の詳細を取得する要求を構築します。- (SFRestRequest*) requestForFileRendition: (NSString*)sfdcId version:(NSString*)version renditionType:(NSString*)renditionType page:(NSUInteger)page;

ファイル (およびバージョン) の特定のページのプレビュー/変換を取得する要求を構築します。- (SFRestRequest*) requestForFileContents: (NSString*) sfdcId version:(NSString*) version;

この特定のファイルの実際のバイナリコンテンツを取得する要求を構築します。- (SFRestRequest*) requestForAddFileShare: (NSString*)fileId entityId:(NSString*)entityId shareType:(NSString*)shareType;

指定されたファイル ID のファイル共有を指定されたエンティティ ID に追加する要求を構築します。- (SFRestRequest*) requestForDeleteFileShare: (NSString*)shareId;

指定されたファイル共有を削除する要求を構築します。- (SFRestRequest*) requestForFileShares: (NSString *)sfdcId page:(NSUInteger)page;

このファイルを共有するエンティティのリストからページを取得する要求を構築します。- (SFRestRequest*) requestForDeleteFileShare: (NSString*)shareId;

指定されたファイル共有を削除する要求を構築します。- (SFRestRequest*) requestForUploadFile: (NSData*)data name:(NSString*)name description: (NSString*)descriptionmimeType: (NSString*)mimeType;

新しいファイルをサーバにアップロードする要求を構築します。バージョンが 1 に設定された新しいファイルを作成します。

認証エラーの処理Mobile SDK には、認証エラーが発生したときにメッセージを表示し、アプリケーションフローを迂回させるデフォルトのエラーハンドラが備えられています。これらのエラーハンドラは、SFAuthErrorHandler クラスのインスタンスです。すべての認証エラーハンドラへの参照を保存する SFAuthErrorHandlerList クラスによって管理されます。エラーハンドラでは、次のプロトタイプを使用する匿名ブロックにその実装が定義されます。typedef BOOL (^SFAuthErrorHandlerEvalBlock)(NSError *, SFOAuthInfo *);

戻り値 YES は現在のエラー状況にこのハンドラが使用されたことを示します。他のどのエラーハンドラも適用されません。ハンドラから NOが返された場合は、このブロックが使用されておらず、エラー処理プロセスはリスト内の次のハンドラに進みます。エラーハンドラの実装の詳細は、開発者の判断に委ねられます。Mobile

SDK でこれらのブロックがどのように定義されるかを確認するには、SalesforceSDKCore プロジェクトのSFAuthenticationManager.m ファイルを参照してください。独自のエラー処理メカニズムに置き換えるには、次の操作を実行します。• 独自のハンドラをエラーハンドラスタックの先頭 (インデックス 0) に追加して、Mobile SDK のデフォルトの

エラーハンドラを上書きします。SFAuthErrorHandler *authErrorHandler =

[[SFAuthErrorHandler alloc] initWithName:@"myAuthErrorHandler"evalBlock:^BOOL(NSError *error, SFOAuthInfo *authInfo) {

77

認証エラーの処理ネイティブ iOS の開発

// Add your error-handling code here}];

[[SFAuthenticationManager sharedManager].authErrorHandlerListaddAuthErrorHandler:authErrorHandler atIndex:0];

• Mobile SDK の汎用「万能」エラーハンドラをリストから削除します。このようにすると、起動プロセス時のSalesforceSDKManager 実装の launchErrorAction ブロック、または遅延ログインを実装した場合はloginWithCompletion:failure:定義の failure:ブロックに認証エラーがそのまま進みます。次に、汎用エラーハンドラを無効化する方法を示します。SFAuthErrorHandler *genericHandler =

[SFAuthenticationManager sharedManager].genericAuthErrorHandler;[[SFAuthenticationManager sharedManager].authErrorHandlerList

removeAuthErrorHandler:genericHandler];

チュートリアル: ネイティブ iOS Warehouse アプリケーションの作成

前提条件• このチュートリアルでは、基本的な在庫データベースを含む Warehouse アプリケーションを使用します。こ

のアプリケーションを DE 組織にインストールする必要があります。既存の DE 組織にインストールする場合、作成した既存の Warehouse コンポーネントをすべて削除してからインストールしてください。1. インストール URL リンク http://goo.gl/1FYg90 をクリックします。2. ログインしている場合は、DE 組織のユーザ名とパスワードを入力します。3. 組織に適した表示レベルを選択します。4. [インストール] をクリックします。5. [完了] をクリックします。6. インストールが完了したら、右上のアプリケーションピッカーから [Warehouse (倉庫)] アプリケーショ

ンを選択できます。

78

チュートリアル: ネイティブ iOS Warehouse アプリケーションの作成

ネイティブ iOS の開発

7. データを作成するには、[データ] タブをクリックします。8. [データを作成] ボタンをクリックします。

• 最新バージョンの Xcode と iOS SDK をインストールします。• www.cocoapods.org の説明に従って CocoaPods をインストールします (Mobile SDK 4.0 以降)。• npm を使用して Salesforce Mobile SDK をインストールします。

1. Node.js および npm がすでに正常にインストールされている場合は、ステップ 4 に進みます。2. Node.js をシステムにインストールします。Node.js インストーラにより、npm が自動的にインストールさ

れます。i. www.nodejs.org から Node.js をダウンロードします。ii. ダウンロードしたインストーラを実行して Node.js および npm をインストールします。インストール

の許可を求めるプロンプトをすべて承諾します。

3. ターミナルウィンドウで、「npm」と入力して Return キーを押し、インストールが成功していることを確認します。使用状況情報のページが表示されない場合、ステップ 2 に戻り、何が欠落しているのかを調べます。

4. ターミナルウィンドウで「sudo npm install forceios -g」と入力します。このコマンドは、forceios パッケージを使用してMobile SDKをグローバルにインストールします。-gオプションでは、npm install を任意のディレクトリから実行できます。npm ユーティリティによりパッケージが /usr/local/lib/node_modules にインストールされ、/usr/local/bin のバイナリモジュールにリンクされます。大部分のユーザは /usr/local の「参照・更新」権限がないため、sudo

オプションが必要になります。

79

チュートリアル: ネイティブ iOS Warehouse アプリケーションの作成

ネイティブ iOS の開発

ネイティブ iOS アプリケーションを作成するこのチュートリアルでは、Salesforce Mobile SDK の使用を開始する方法 (SDK のインストール方法や DE 組織を使用したネイティブプロジェクトテンプレートのツアーを含む) を学習します。後続のチュートリアルでは、テンプレートアプリケーションを変更して、Warehouse スキーマと連携させる方法について説明します。

ステップ 1: 接続アプリケーションを作成するこのステップでは、Force.com で接続アプリケーションを設定する方法を学習します。これを行うことで構築するモバイルアプリケーションが認証され、ユーザの代わりに業界標準の OAuth 2.0 プロトコルを介して Force.com

と安全に通信し、Force.com API にアクセスできるようになります。1. Developer Edition 組織で、[設定] から [クイック検索]ボックスに「アプリケーション」と入力し、[アプリケー

ション] を選択します。2. [接続アプリケーション] で、[新規] をクリックして、[新規接続アプリケーション] ページを表示します。3. [基本情報] で、フォームに次のように入力します。

• 接続アプリケーション名: My Native iOS App (私のネイティブ iOS アプリケーション)

• API 参照名: 推奨値を受け入れます。• 取引先責任者メール: メールアドレスを入力します。

4. OAuth 設定で [OAuth 設定の有効化] をオンにします。5. [コールバック URL] を mysampleapp://auth/success に設定します。6. [利用可能な OAuth 範囲] で、次のチェックボックスをオンにします。

• データへのアクセスと管理 (api)

• Web 経由のデータへのアクセスを提供 (web)

• ユーザに代わっていつでも要求を実行 (refresh_token、offline_access)

7. [追加] をクリックします。8. [保存] をクリックします。設定を保存すると、作成した接続アプリケーションの詳細が表示されます。• [コールバック URL] と [コンシューマ鍵] の値をメモします。これらは、次のステップでアプリケーショ

ンを設定するときに使用します。• モバイルアプリケーションではコンシューマの秘密は使用しないため、この値は無視できます。

80

ネイティブ iOS アプリケーションを作成するネイティブ iOS の開発

ステップ 2: ネイティブ iOS プロジェクトを作成する新しい Mobile SDK プロジェクトを作成するには、ターミナルウィンドウで forceios ユーティリティを再度使用します。1. プロジェクトを作成するディレクトリに変更します。2. iOS プロジェクトを作成するには、「forceios create」と入力します。

設定値ごとに、forceios ユーティリティによってプロンプトが表示されます。

3. アプリケーション種別に、「native」と入力します。4. アプリケーション名に、「MyNativeiOSApp」と入力します。5. 出力ディレクトリに、「tutorial/iOSNative」と入力します。6. 会社の識別子に、「com.acme.goodapps」と入力します。7. 組織名に、「GoodApps, Inc.」と入力します。8. 接続アプリケーション ID に、接続アプリケーション定義からコンシューマ鍵をコピーして貼り付けます。9. 接続アプリケーションのコールバック URI に、接続アプリケーション定義からコールバック URL をコピーし

て貼り付けます。入力画面は次のように表示されます。Enter your application type (native, native_swift, react_native,

hybrid_remote, or hybrid_local): nativeEnter your application name: MyNativeiOSAppEnter the output directory for your app (defaults to the current directory):tutorial/iOSNativeEnter the package name for your app (com.mycompany.my_app): com.acme.goodappsEnter your organization name (Acme, Inc.): GoodApps, Inc.Enter your Connected App ID (defaults to the sample app's ID):Enter your Connected App Callback URI (defaults to the sample app's URI):Creating output folder tutorial/iOSNativeCreating app in /Users/rwhitley/SalesforceMobileSDK-iOS/tutorial/iOSNative/MyNativeiOSAppSuccessfully created native app ‘MyNativeiOSApp’

ステップ 3: 新しい iOS アプリケーションを実行する1. Xcode で [File (ファイル)] > [Open (開く)] を選択します。2. 指定した出力フォルダに移動します。3. アプリケーションの xcworkspace ファイルを開きます。4. Xcode ツールバーでシミュレータデバイスを選択し、[実行] をクリックします。

アプリケーションを起動すると、初期スプラッシュ画面が表示された後で Salesforce ログイン画面が表示されます。

5. DE のユーザ名とパスワードを使用してログインします。6. プロンプトが表示されたら、アプリケーションの左にある [Allow (許可)] をクリックして、Salesforce のデー

タにアクセスします。DE 組織で定義されているユーザ名のリストを示す表が表示されます。

81

ネイティブ iOS アプリケーションを作成するネイティブ iOS の開発

ステップ 4: iOS アプリケーションの仕組みを探索するネイティブ iOS アプリケーションは、簡単な Model View Controller (MVC) アーキテクチャを使用します。• モデルは、Force.com データベーススキーマです。• ビューは、プロジェクト内の nib ファイルおよび実装ファイルから取得されます。• コントローラの機能は、iOS SDK クラス、Salesforce Mobile SDK、および各自のアプリケーションを接続するこ

とです。

AppDelegate クラスとルートビューコントローラアプリケーションが起動すると、AppDelegate クラスが初めに実行フローを制御します。ログインプロセスが完了すると、AppDelegateインスタンスからルートビューに制御が移ります。テンプレートアプリケーションでは、ルートビューコントローラクラスの名前は RootViewController になっています。このクラスはAppDelegate.mファイルでアプリケーションのルートビューとなり、ビュー間のナビゲーションを制御するUINavigationController インスタンスによって組み込まれます。- (void)setupRootViewController{

RootViewController *rootVC = [[RootViewController alloc]

82

ネイティブ iOS アプリケーションを作成するネイティブ iOS の開発

initWithNibName:nil bundle:nil];UINavigationController *navVC = [[UINavigationController alloc]

initWithRootViewController:rootVC];self.window.rootViewController = navVC;

}

ただし、カスタマイズするまでは、アプリケーションに他のビューやタッチイベントハンドラは含まれていません。Salesforce にログインし、Salesforce Mobile SDK と REST API を使用して要求を発行し、ルートビューに応答を表示するのみです。

UITableViewController クラスRootViewController は、UITableViewController クラスを継承します。継承されたビューに含まれるテーブルはカスタマイズしないため、nib ファイルまたは xib ファイルは不要です。コントローラクラスはtableView プロパティにデータを読み込むだけで、ほとんどの表示タスクはスーパークラスが処理します。ただし、RootViewController は、tableView:cellForRowAtIndexPath: メソッドをコールすることにより、セルの一部の基本的な書式設定を追加します。新しいセルを作成し、それに汎用的な ID

(@"CellIdentifier") を割り当て、セルの左側にアイコンを配置し、右側に矢印を追加します。最も重要なのは、REST 応答オブジェクトから現在の行の Name 値を想定するためのセルの表示ラベルを設定する点です。次にコードを示します。// Customize the appearance of table view cells.- (UITableViewCell *)tableView:(UITableView *)tableView_

cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"CellIdentifier";

// Dequeue or create a cell of the appropriate type.UITableViewCell *cell = [tableView_

dequeueReusableCellWithIdentifier:CellIdentifier];if (cell == nil) {

cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1

reuseIdentifier:CellIdentifier];}//if you want to add an image to your cell, here's howUIImage *image = [UIImage imageNamed:@"icon.png"];cell.imageView.image = image;

// Configure the cell to show the data.NSDictionary *obj =

[dataRows objectAtIndex:indexPath.row];cell.textLabel.text = [obj objectForKey:@"Name"];

//this adds the arrow to the right hand side.cell.accessoryType =

UITableViewCellAccessoryDisclosureIndicator;

return cell;

}

83

ネイティブ iOS アプリケーションを作成するネイティブ iOS の開発

SFRestAPI 共有オブジェクトと SFRestRequest クラスRootViewController.viewDidLoad メソッドを確認すると、REST 要求がアプリケーションでどのように作成および送信されるかがわかります。アプリケーションでは SOQL クエリのリテラル文字列が定義され、SFRestAPI:requestForQuery: インスタンスメソッドに渡されます。このメソッドをコールするために、アプリケーションは共有シングルトン SFRestAPI インスタンスにメッセージを送信します。メソッドは、SOQL クエリをラップする書式設定済みの適切な SFRestRequest オブジェクトを作成し、それを返します。次に、send:delegate:メッセージを共有 SFRestAPIオブジェクトに送信することで、アプリケーションはこのオブジェクトをサーバに転送します。

SFRestRequest *request = [[SFRestAPI sharedInstance]requestForQuery:@"SELECT Name FROM User LIMIT 10"];

[[SFRestAPI sharedInstance] send:request delegate:self];

SFRestAPI クラスは、SFRestRequest インスタンスのファクトリとしての役割を果たします。このクラスは、要求オブジェクトを簡単に作成するためにコールできる一連の要求メソッドを定義します。必要に応じてSFRestRequestインスタンスを直接作成することもできますが、ほとんどの場合は手動による作成は不要です。アプリケーションでは、delegate 引数に self が指定されます。これにより、RootViewController クラスで実装された代理メソッドに応答を送信するようサーバに指示されます。

SFRestDelegate インターフェースREST 応答の受け入れを可能にするため、RootViewController では SFRestDelegate インターフェースが実装されます。このインターフェースでは、4 つメソッド (考えられる応答種別ごとに 1 つ) が宣言されます。要求に成功すると、request:didLoadResponse: 代理メソッドが実行されます。RootViewController でrequest:didLoadResponse: コールバックが受信されると、返されたレコードがデータ行にコピーされ、ビューに表示されたデータが再度読み込まれます。次に、RootViewControllerクラスで SFRestDelegate

インターフェースを実装するコードを示します。#pragma mark - SFRestDelegate

- (void)request:(SFRestRequest *)requestdidLoadResponse:(id)jsonResponse {

NSArray *records = [jsonResponse objectForKey:@"records"];NSLog(@"request:didLoadResponse: #records: %lu", (unsigned long)records.count);self.dataRows = records;dispatch_async(dispatch_get_main_queue(), ^{

[self.tableView reloadData];});

}

- (void) request:(SFRestRequest*)requestdidFailLoadWithError:(NSError*)error {

NSLog(@"request:didFailLoadWithError: %@", error);//add your failed error handling here

}

- (void)requestDidCancelLoad:(SFRestRequest *)request {NSLog(@"requestDidCancelLoad: %@", request);

84

ネイティブ iOS アプリケーションを作成するネイティブ iOS の開発

//add your failed error handling here}

- (void)requestDidTimeout:(SFRestRequest *)request {NSLog(@"requestDidTimeout: %@", request);//add your failed error handling here

}

コメントで示されるように、このコピーは、request:didLoadResponse:で代理メソッドが成功した場合にのみ完全に実装されます。成功以外の応答の場合は、このテンプレートアプリケーションはメッセージをログ記録するのみです。

リスト画面をカスタマイズするこのチュートリアルでは、Warehouse スキーマ固有のアプリケーションとなるようにルートビューコントローラを変更します。また、Merchandise カスタムオブジェクトから必要なすべての情報を取得できるように、既存の SOQL クエリを適合させます。

ステップ 1: ルートビューコントローラを変更するWarehouse 設計にテンプレートプロジェクトを適合させるため、RootViewControllerクラスの名前を変更しましょう。1. プロジェクトナビゲータで、RootViewController.h ファイルを選択します。2. エディタで、次の行の「RootViewController」という名前をクリックします。

@interface RootViewController : UITableViewController <SFRestDelegate>{

3. Ctrl+クリックメニューを使用して、[Refactor (再構成)] > [Rename (名前を変更)]を選択します。[Rename Related

Files (関連ファイルの名前を変更)] がオンになっていることを確認します。4. 「RootViewController」を「WarehouseViewController」に変更します。[Preview (プレビュー)]をクリックします。

Xcode に新しいウィンドウが表示され、左側に「RootViewController」という名前を含むすべてのプロジェクトファイルのリストが表示されます。中央のペインには、変更されたファイルごとに、既存のバージョンと提案された新バージョンとの相違が表示されます。

5. [Save (保存)] をクリックします。Refactoring ウィンドウが非表示になり、リファクタリングされたプロジェクトに戻ります。RootViewController.h および RootViewController.m というファイル名が、WarehouseViewController.h および WarehouseViewController.m になりました。プロジェクトコード内の RootViewController のすべてのインスタンスも、WarehouseViewController に変更されました。

ステップ 2: アプリケーションのルートビューを作成するネイティブ iOS テンプレートアプリケーションでは、標準 User オブジェクトから Name 項目を抽出する SOQL クエリが作成されます。ただし、このチュートリアルでは、カスタムオブジェクトのレコードを使用します。[Name (名前)]、[Quantitiy (数量)]、[Price (価格)] 項目を表示する詳細画面は、後から作成します。また、レコードID も必要です。

85

リスト画面をカスタマイズするネイティブ iOS の開発

カスタム Merchandise__c オブジェクトを操作する SOQL クエリを更新し、詳細画面に必要な項目を取得してみましょう。1. プロジェクトナビゲータで、WarehouseViewController.m を選択します。2. viewDidLoad メソッドまでスクロールします。3. ビューの表示名を「Warehouse App」に更新します。次の行を変更します。

self.title = @"Mobile SDK Sample App"

変更後self.title = @"Warehouse App"

4. 次の行で SOQL クエリを変更します。SFRestRequest *request = [[SFRestAPI sharedInstance] requestForQuery:@"SELECT NameFROM User LIMIT 10"];

変更後SELECT Name, Id, Quantity__c, Price__c FROM Merchandise__c LIMIT 10

メモ: まれに、開発者は Merchandise テーブルを手動で作成することがあります。これを行った場合、各カスタムオブジェクトおよび項目の API 名の先頭に 4 文字の開発者のプレフィックスを指定する必要があります。このルールは、SOQL ステートメントやアプリケーションのその他の各用途に適用されます。たとえば、開発者のプレフィックスが「ABCD」の場合、Merchandise__c オブジェクトの API 名はABCD__Merchandise__c になります。

ステップ 3: アプリケーションを試すアプリケーションを作成して実行します。プロンプトが表示されたら、DE 組織にログインします。初期ページに、次のような画面が表示されます。

86

リスト画面をカスタマイズするネイティブ iOS の開発

この時点で Merchandise レコードをクリックしても何も起きません。次のチュートリアルでこれを修正します。

詳細画面を作成する前のチュートリアルで、起動後に最大 10 個の Merchandise レコードを一覧表示するようにテンプレートアプリケーションを変更しました。このチュートリアルでは、詳細ビューおよびコントローラを作成して作業を終了します。また、リストビューコントローラと詳細ビューコントローラ間の通信も確立します。

ステップ 1: アプリケーションの詳細ビューコントローラを作成するWarehouse ビューでユーザが Merchandise レコードをタップすると、IBActionはレコード固有の情報を生成し、この情報を表示する DetailViewControllerからビューを読み込みます。ただし、このビューはまだ存在しないので作成しましょう。1. [File (ファイル)] > [New (新規)] > [File... (ファイル...)]をクリックして [Source (ソース)] > [Cocoa Touch Class (Cocoa

Touch クラス)] を選択します。2. [Next (次へ)] をクリックします。3. 次のプロパティを設定します。

87

詳細画面を作成するネイティブ iOS の開発

値プロパティ

DetailViewControllerClass (クラス)

UIViewControllerSubclass of (次のサブクラス)

オン、[iPhone]Also create XIB file (XIB ファイルも作成)

Objective-CLanguage (言語)

4. [Groups (グループ)] ドロップダウンメニューの [MyNativeiOSApp] の [Classes (クラス)] グループに新しいクラスを配置します。

5. [Create (作成)]をクリックします。Xcode により、Classes フォルダに 3 つの新しいファイル (DetailViewController.h、DetailViewController.m、DetailViewController.xib) が作成されます。

6. プロジェクトナビゲータで DetailViewController.xib を選択し、Interface Builder を開きます。7. [Utilities (ユーティリティ)] ビュー から、[Attributes (属性)] インスペクタを選択します。8. フレームの何もないスペースをクリックし、[Simulated Metrics (シミュレートされた総計値)] の [Size (サイズ)]

ドロップダウンメニューから iPhone 設定を選択します。9. 右下のパネルに、オブジェクトライブラリ が表示されます。3 つの表示ラベル、2 つのテ

キスト項目、および 1 つのボタンをビューレイアウトにドラッグします。次のような画面になるようにコントロールを並び替えてサイズを変更します。

88

詳細画面を作成するネイティブ iOS の開発

最上部の表示ラベルを「名前表示ラベル」と呼ぶことにします。この表示ラベルは動的です。次のチュートリアルでは、実行時にこれを適切な値にリセットするコントローラコードを追加します。

10. [Attributes (属性)] インスペクタで、価格および数量の静的な表示ラベルの表示テキストに下図の表示値を設定します。Interface Builder で各表示ラベルを個別に選択し、[Text (テキスト)] ドロップダウンメニューの下にある名前のない入力項目で表示テキストを指定します。

メモ: 必要に応じて表示ラベルの幅を調整し、表示テキストがすべて表示されるようにします。[名前]

表示ラベルには、画面幅の約 2/3 が必要です。

11. [Attributes (属性)] インスペクタで、更新ボタンの表示テキストを下図の表示値に設定します。Interface Builder

でボタンを選択し、[Title (タイトル)] ドロップダウンメニューの下にある名前のない入力項目でその表示テキストを指定します。

89

詳細画面を作成するネイティブ iOS の開発

12. 構築して実行し、エラーを確認します。まだ変更は表示されません。詳細ビューの設計には、[Price (価格)] 項目、[Quantitiy (数量)] 項目、およびレコードの数量を更新するためのボタンが表示されています。ただし、現時点では何も機能しません。次のステップでは、この設計を Warehouse レコードに接続する方法を学習します。

ステップ 2: DetailViewController を設定するビュー要素とそれらのビューコントローラ間の接続を確立するには、Xcode Interface Builder を使用して、UI 要素とコード要素を接続します。

インスタンスプロパティを追加する1. DetailViewController.hに、WarehouseViewControllerによって渡される値を格納するプロパティ

(名前、数量、価格、ID) を作成します。これらのプロパティを @interface ブロック内に配置します。次の名前を使用して、それぞれの nonatomic および strong を宣言します。@interface DetailViewController : UIViewController

@property (nonatomic, strong) NSNumber *quantityData;@property (nonatomic, strong) NSNumber *priceData;@property (nonatomic, strong) NSString *nameData;@property (nonatomic, strong) NSString *idData;

@end

2. DetailViewController.m の @implementation タグの直後に各プロパティを合成します。

@implementation DetailViewController

@synthesize nameData;@synthesize quantityData;@synthesize priceData;@synthesize idData;

IBOutlet 変数を追加するIBOutletメンバー変数を使用すると、コントローラが各非静的コントロールを管理できます。手動でこれらをコーディングする代わりに、Interface Builder を使用して作成できます。Interface Builder には、便利な横並びの編集ウィンドウがあるアシスタントエディタが用意されています。アシスタントエディタ用の領域を確保するには、使用していないコントロールを非表示にして画面領域を再要求します。

90

詳細画面を作成するネイティブ iOS の開発

1. プロジェクトナビゲータで、DetailViewController.xib ファイルをクリックします。DetailViewController.xib ファイルが標準エディタで開きます。

2. [View (表示)] ツールバー の [Hide or Show Navigator (ナビゲータを表示/非表示)] をクリックして、ナビゲータを非表示にします。

3. [Editor (エディタ)] ツールバー の [Show the Assistant editor (アシスタントエディタを表示)] をクリックして、アシスタントエディタを開きます。アシスタントエディタに DetailViewController.h ファイルが表示されていることを確認します。アシスタントエディタは、一緒に使用する可能性の最も高いファイルを推測します。別のファイルを開く必要がある場合、アシスタントエディタの左上隅にある [Related Files (関連ファイル)] コントロールをクリックします。

4. DetailViewController.h のインターフェースブロックの上部に、空の中括弧のペアを追加します。@interface DetailViewController : UiViewController <SFRestDelegate>{

}

5. 標準エディタで、Ctrl キーを押しながら [Price (価格)] テキスト項目コントロールをクリックし、DetailViewController.h ファイルの新しい中括弧ブロックにドラッグします。

6. ポップアップダイアログボックスで、新しいアウトレット _priceField に名前を付けて [Connect (接続)]

をクリックします。7. [Quantity (数量)] テキスト項目についてステップ 2 と 3 を繰り返し、そのアウトレット _quantityField に

名前を付けます。8. 名前表示ラベルについてステップ 2 と 3 を繰り返し、そのアウトレット _nameLabel に名前を付けます。

91

詳細画面を作成するネイティブ iOS の開発

これで、インターフェースコードに次のブロックが含まれるようになりました。@interface DetailViewController : UIViewController{

__weak IBOutlet UITextField *_priceField;__weak IBOutlet UITextField *_quantityField;__weak IBOutlet UILabel *_nameLabel;

}

更新ボタンイベントを追加する1. Interface Builder で、[Update (更新)]ボタンを選択し、[Connections (接続)] インスペクタ

を開きます。2. [Connections (接続)] インスペクタで、[Touch Up Inside (タッチアップ (内))] の横にある円を選択し、

DetailViewController.h ファイルにドラッグします。閉じ中括弧の下にドロップしてください。updateTouchUpInside という名前を付けて [Connect (接続)] をクリックします。Touch Up Inside イベントは、ユーザが更新ボタンに触れている指をボタン領域内で上げたことを通知します。この通知を受信するたびにレコードの更新を実行します。

ステップ 3: 指定のイニシャライザを作成するでは、コーディングに取り掛かりましょう。まず、名前、ID、数量、および価格を取得するDetailViewControllerに新しいイニシャライザメソッドを追加します。メソッド名は、命名規則に従って「init」で開始する必要があります。1. [Show the Standard Editor (標準エディタを表示)] をクリックして、ナビゲータを開きます。2. この宣言を DetailViewController.h ファイルにある @end マーカーのすぐ上に追加します。

- (id) initWithName:(NSString *)recordNamesobjectId:(NSString *)salesforceIdquantity:(NSNumber *)recordQuantity

price:(NSNumber *)recordPrice;

後で、このメソッドを使用してデータを DetailViewController に渡すようにWarehouseViewController をコーディングします。

3. DetailViewController.mファイルを開き、前のステップで作成した署名をファイルの最後にある @end

マーカーのすぐ上にコピーします。4. 実装ブロックのために、終了を示すセミコロンを中括弧のペアで置き換えます。

- (id) initWithName:(NSString *)recordNamesobjectId:(NSString *)salesforceIdquantity:(NSNumber *)recordQuantity

price:(NSNumber *)recordPrice {}

5. メソッド本文で、init メッセージをスーパークラスに送信します。戻り値を self に割り当てます。self = [super init];

92

詳細画面を作成するネイティブ iOS の開発

この init メッセージで、戻り値として機能する基本的な実装を備えた機能オブジェクトを提供します。

6. スーパークラスの初期化が成功しているかどうかを確認し、成功している場合はメソッド引数を対応するインスタンス変数に割り当てるためのコードを追加します。最後に、self を返します。if (self) {

self.nameData = recordName;self.idData = salesforceId;self.quantityData = recordQuantity;self.priceData = recordPrice;

}return self;

次に、完成したメソッドを示します。- (id) initWithName:(NSString *)recordName

sobjectId:(NSString *)salesforceIdquantity:(NSNumber *)recordQuantity

price:(NSNumber *)recordPrice {self = [super init];if (self) {

self.nameData = recordName;self.idData = salesforceId;self.quantityData = recordQuantity;self.priceData = recordPrice;

}return self;

}

7. ビューが表示されるたびにコントロールが更新されていることを確認するには、viewDidLoadメソッド実装の後に新しい viewWillAppear: イベントハンドラを追加します。まず、スーパークラスのメソッドをコールします。- (void)viewWillAppear:(BOOL)animated {

[super viewWillAppear:animated];

}

8. プロパティ変数の値を対応する動的なコントロールにコピーします。- (void)viewWillAppear:(BOOL)animated {

[super viewWillAppear:animated];[_nameLabel setText:self.nameData];[_quantityField setText:[self.quantityData stringValue]];[_priceField setText:[self.priceData stringValue]];

}

9. プロジェクトを構築して実行し、すべてのコーディングが完了していて、コンパイルエラーが発生していないことを確認します。詳細ビューを起動するコードをまだ追加していないため、アプリケーションは最初の状態と変わらないように見えます。

メモ: initWithName: メソッドで使用される [super init] メッセージは、内部的に [super

initWithNibName:bundle:]をコールします。NIB 名またはバンドルを渡さないため、ここでは [super

93

詳細画面を作成するネイティブ iOS の開発

init] を使用します。独自のプロジェクトでこれらのリソースを指定する場合、[super

initWithNibName:bundle:] を明示的にコールする必要があります。

ステップ 4: ビューコントローラ間の通信を確立するSalesforce コンテンツを使用するビューは、SFRestAPI 代理オブジェクトを使用してそのコンテンツを取得します。アプリケーションのすべてのビューを一元管理する代理オブジェクトとして 1 つのビューを指定できますが、ビューコントローラ間の正確な通信が必要となります。この練習課題では、WarehouseViewController

と DetailViewController をそれぞれ独自のSFRestAPI 代理オブジェクトとして機能させる少し簡単な方法を使用します。

WarehouseViewController を更新するまず、WarehouseViewController を用意して、選択したレコードの数量および価格の値を詳細ビューに渡し、そのビューを表示しましょう。1. WarehouseViewController.m の @implementation ブロックの上に次の行を追加します。

#import "DetailViewController.h"

2. #pragma mark – Table view data sourceマーカーの後にある新しい行で、UITableView代理メソッドのリストを表示する次の開始テキストを入力します。- (void)tableView

3. リストから、tableView:didSelectRowAtIndexPath: メソッドを選択します。4. tableView パラメータの名前を itemTableView に変更します。

- (void)tableView:(UITableView *)itemTableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath

5. 署名の最後に、開き中括弧 ({) を入力して Enter キーを押し、メソッド実装ブロックにスタブを作成します。6. メソッド本文の上部で、標準 iOS コーディングプラクティスごとに、行の選択解除を行う次のコールを追加

します。[itemTableView deselectRowAtIndexPath:indexPath animated:NO];

7. 次に、選択したデータ行に関連付けられている NSDictionaryオブジェクトへのポインタを取得します。NSDictionary *obj = [self.dataRows objectAtIndex:indexPath.row];

8. メソッド本文の最後で、DetailViewController.initWithName:salesforceId:quantity:price:

メソッドをコールして DetailViewController のローカルインスタンスを作成します。NSDictionary

オブジェクトに保存されているデータを使用して、名前、Salesforce ID、数量、および価格の引数を設定します。完成したコールは次のようになります。DetailViewController *detailController =

[[DetailViewController alloc]initWithName:[obj objectForKey:@"Name"]

sobjectId:[obj objectForKey:@"Id"]

94

詳細画面を作成するネイティブ iOS の開発

quantity:[obj objectForKey:@"Quantity__c"]price:[obj objectForKey:@"Price__c"]];

9. 詳細ビューを表示するには、初期化した DetailViewController を UINavigationController スタックにプッシュするコードを追加します。

[[self navigationController] pushViewController:detailController animated:YES];

これで、UINavigationController スタックを使用して、2 つのビューのセットを処理します。ルートビューコントローラは、常にスタックの下部にあります。他のビューを有効化するには、そのコントローラをスタックにプッシュします。ビューを閉じるときに、そのコントローラをポップします。これにより、その下のビューが再表示されます。

10. アプリケーションを構築して実行します。詳細を表示する Warehouse 項目をクリックします。

更新機能を追加するこれで WarehouseViewController が設定されたので、REST 要求を使用してユーザの更新を Salesforce に送信するように DetailViewController クラスを変更する必要があります。1. DetailViewController.h ファイルで、インスタンスメソッドを DetailViewController に追加し、

ユーザが価格および数量の項目を更新できるようにします。このメソッドは、レコード ID、更新する項目名、新しい数量と価格の値、および更新するオブジェクト名を送信する必要があります。インターフェースブロックの後 (@end マーカーのすぐ上) にこの宣言を追加します。- (void)updateWithObjectType:(NSString *)objectType

objectId:(NSString *)objectIdquantity:(NSString *)quantityprice:(NSString *)price;

メソッドを実装するには、入力値を使用して SFRestRequest オブジェクトを作成し、要求オブジェクトを SFRestAPI の共有インスタンスに送信します。

2. DetailViewController.h ファイルの @interface 宣言のすぐ上に次の import ステートメントを追加します。#import "SFRestAPI.h"

3. DetailViewController.h ファイルの最後にある @end マーカーのすぐ上に、updateWithObjectType:objectId:quantity:price: 署名をコピーし、その後に中括弧のペアを追加します。- (void)updateWithObjectType:(NSString *)objectType

objectId:(NSString *)objectIdquantity:(NSString *)quantity

price:(NSString *)price {

}

95

詳細画面を作成するネイティブ iOS の開発

4. 実装ブロックで、[Quantitiy (数量)] 項目と [Price (価格)] 項目を格納する新しい NSDictionary オブジェクトを作成します。このオブジェクトを割り当てるには、目的の項目リストを含むdictionaryWithObjectsAndKeys: ... NSDictionary クラスメソッドを使用します。- (void)updateWithObjectType:(NSString *)objectType

objectId:(NSString *)objectIdquantity:(NSString *)quantity

price:(NSString *)price{

NSDictionary *fields = [NSDictionarydictionaryWithObjectsAndKeys: quantity, @"Quantity__c",

price, @"Price__c",nil];

}

5. SFRestRequest オブジェクトを作成します。このオブジェクトを割り当てるには、SFRestAPI 共有インスタンスで requestForUpdateWithObjectType:objectId:fields:インスタンスメソッドを使用します。- (void)updateWithObjectType:(NSString *)objectType

objectId:(NSString *)objectIdquantity:(NSString *)quantity

price:(NSString *)price{

NSDictionary *fields = [NSDictionarydictionaryWithObjectsAndKeys: quantity, @"Quantity__c",

price, @"Price__c",nil];

SFRestRequest *request = [[SFRestAPI sharedInstance]requestForUpdateWithObjectType:objectType

objectId:objectIdfields:fields];

}

6. 最後に、SFRestAPI 共有インスタンスで send:delegate: をコールして、新しい SFRestRequest オブジェクトをサービスに送信します。この場合、DetailViewController が SFRestDelegate であるため、delegate 引数には self を指定してください。- (void)updateWithObjectType:(NSString *)objectType

objectId:(NSString *)objectIdquantity:(NSString *)quantity

price:(NSString *)price{

NSDictionary *fields = [NSDictionarydictionaryWithObjectsAndKeys: quantity, @"Quantity__c",

price, @"Price__c",nil];

SFRestRequest *request = [[SFRestAPI sharedInstance]requestForUpdateWithObjectType:objectType

96

詳細画面を作成するネイティブ iOS の開発

objectId:objectIdfields:fields];

[[SFRestAPI sharedInstance] send:request delegate:self];}

7. ユーザが [更新] ボタンをタップしたときに updateWithObjectType:objectId:quantity:price: メソッドをコールするように updateTouchUpInside: アクションメソッドを編集します。- (IBAction)updateTouchUpInside:(id)sender {

// For Update button[self updateWithObjectType:@"Merchandise__c"

objectId:self.idDataquantity:[_quantityField text]

price:[_priceField text]];}

メモ:

• 追加課題: ユーザが実際に数量の値を変更したときにだけ更新が実行されるようにアプリケーションを効率化しましょう。

SFRestDelegate を DetailViewController に追加するもう少しで作業は終了します。REST 要求を発行しましたが、まだ応答を処理するコードを入力する必要があります。1. DetailViewController.h ファイルを開き、<SFRestDelegate> が含まれるように

DetailViewController インターフェース宣言を変更します。@interface DetailViewController : UIViewController <SFRestDelegate>

2. WarehouseViewController.m ファイルを開きます。3. SFRestAPIDelegate セクションをマークする pragma を探します。

#pragma mark - SFRestAPIDelegate

メモ: テンプレートの SFRestAPIDelegateはスペルミスです。プロトコルの名前は SFRestDelegate

です。皆様が本書を読む頃には、修正されている予定です。

4. この pragma の下にある 4 つのメソッドを DetailViewController.m ファイルにコピーします。- (void)request:(SFRestRequest *)request didLoadResponse:(id)jsonResponse {

NSArray *records = [jsonResponse objectForKey:@"records"];NSLog(@"request:didLoadResponse: #records: %d",

records.count);self.dataRows = records;[self.tableView reloadData];

}

- (void)request:(SFRestRequest*)request didFailLoadWithError:(NSError*)error {NSLog(@"request:didFailLoadWithError: %@", error);//add your failed error handling here

97

詳細画面を作成するネイティブ iOS の開発

}

- (void)requestDidCancelLoad:(SFRestRequest *)request {NSLog(@"requestDidCancelLoad: %@", request);//add your failed error handling here

}

- (void)requestDidTimeout:(SFRestRequest *)request {NSLog(@"requestDidTimeout: %@", request);//add your failed error handling here

}

SFRestAPIインターフェースを実装するのに必要なのは、これらのメソッドだけです。このチュートリアルでは、エラー、キャンセル、およびタイムアウト条件の単純な処理を保持できます。ただし、request:didLoadResponse: メソッドでコンパイルエラーが生成されます。request:didLoadResponse: メソッドは詳細ビューの目的に合わせて変更する必要があります。エラーを回避し、UINavigationControllerスタックを使用して、更新実行後にリストビューに戻りましょう。

5. DetailViewController.m ファイルで、request:didLoadResponse: 代理メソッドの既存のコードを削除します。その場所に、成功メッセージを記録してすぐにルートビューコントローラに戻るコードを追加します。修正したメソッドは次のようになります。

- (void)request:(SFRestRequest *)requestdidLoadResponse:(id)jsonResponse {

NSLog(@"1 record updated");dispatch_async(dispatch_get_main_queue(), ^{

[self.navigationController popViewControllerAnimated:YES];});

}

6. アプリケーションを構築して実行します。Warehouse ビューで、いずれかの項目をクリックします。これで、詳細ビューにアクセスしてその数量を編集できますが、キーボードを非表示にしたいときに非表示にならないという問題があります。アプリケーションが完全に機能するには、もう少し工夫が必要です。

viewWillAppear を使用したクエリの更新viewDidLoadメソッドでは、最初に読み込まれたときのビューを設定できます。WarehouseViewController

実装では、リストビューと詳細ビューの両方を入力する REST API クエリがこのメソッドにあります。ただし、WarehouseViewController はルートビューを表しているため、viewDidLoad 通知はビューの初期化時に 1

回しかコールされません。これはどういう意味でしょうか? ユーザが詳細ビューで数量を更新してリストビューに戻っても、クエリは更新されません。そのため、詳細ビューの同じレコードに戻っても、ユーザが期待する更新された値は表示されません。クエリを処理するには、別のメソッドが必要です。viewWillAppear メソッドは、そのビューが表示されるたびにコールされます。このメソッドを WarehouseViewControllerに追加して、SOQL クエリをそこに移動しましょう。

98

詳細画面を作成するネイティブ iOS の開発

1. WarehouseViewController.m ファイルの viewDidLoad 実装の後に次のコードを追加します。- (void)viewWillAppear:(BOOL)animated {

[super viewWillAppear:animated];

}

2. viewDidLoad メソッドから次の行をカットして、viewWillAppear: メソッドの super へのコールの後に貼り付けます。

SFRestRequest *request =[[SFRestAPI sharedInstance] requestForQuery:

@"SELECT Name, ID, Price__c, Quantity__c ""FROM Merchandise__c LIMIT 10"];

[[SFRestAPI sharedInstance] send:request delegate:self];

最終的な viewDidLoad および viewWillAppear: メソッドは次のようになります。- (void)viewDidLoad{

[super viewDidLoad];self.title = @"Warehouse App";

}

- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];SFRestRequest *request = [[SFRestAPI sharedInstance]

requestForQuery:@"SELECT Name, ID, Price__c, ""Quantity__c ""FROM Merchandise__c LIMIT 10"];

[[SFRestAPI sharedInstance] send:request delegate:self];}

viewWillAppear:メソッドは、ユーザがリストビューに戻るたびにクエリを更新します。後でユーザが詳細ビューに再度アクセスすると、リストビューコントローラは、更新されたデータで詳細ビューを更新します。

ステップ 5: アプリケーションを試す1. アプリケーションを構築し、iPhone エミュレータで実行します。すべて適切に行った場合、Warehouse 画面

の Merchandise レコードをクリックしたときに詳細ページが表示されます。2. レコードの数量と価格を更新します。値を編集した後で詳細ビューの [更新] ボタンをクリックしてくださ

い。詳細ビューに戻ると、更新された値が表示されます。3. DE 組織にログインして、ブラウザ UI でレコードを表示し、更新された値を確認します。

iOS サンプルアプリケーション

「Xcode プロジェクトのテンプレートアプリケーションを実行する」で作成したアプリケーション自体はサンプルアプリケーションですが、その実行内容は SOQL クエリを発行し、結果を返すのみです。ネイティブの iOS

サンプルアプリケーションには、独自のアプリケーションで確認および操作できる多くの機能が含まれています。

99

iOS サンプルアプリケーションネイティブ iOS の開発

• RestAPIExplorer では、ネイティブのすべての REST API ラッパーが実行されます。これは、native/SampleApps/RestAPIExplorer の Mobile SDK for iOS にあります。

• SmartSyncExplorer には、iOS 上でのネイティブ SmartSync ライブラリの機能が示されます。これは、native/SampleApps/SmartSyncExplorer の Mobile SDK for iOS にあります。

Mobile SDK には、次のハイブリッドアプリケーション用の iOS ラッパーが用意されています。• AccountEditor: smartsync.js ライブラリを使用してオフラインデータを同期する方法について説明しま

す。• NoteSync: 非 REST API を使用して Salesforce のメモを取得する方法を示します。• SmartSyncExplorerHybrid: SmartSync プラグインを使用してオフラインデータを同期する方法について説明し

ます。

100

iOS サンプルアプリケーションネイティブ iOS の開発

第 8 章 ネイティブ Android の開発

Salesforce Mobile SDK for Android には、ソースコード、開発スクリプト、ネイティブサンプルアプリケーションが揃っているため、すぐに開発に着手できます。また、Mobile

トピック:

• Android ネイティブクイックスタート

SDKアプリケーションの 2 つの基本的な機能を実装するテンプレートアプリケーションが用意されています。

• ネイティブ Androidの要件

• OAuth2 認証フローの自動化。これにより、プロセスをアプリケーションに統合しやすくなります。

• Android プロジェクトの作成 • Salesforce REST API へのアクセス。アクセスを簡略化するユーティリティクラスが

使用されます。• Android Studio でのサンプルプロジェクトの設定

サンプルネイティブアプリケーションは、ログイン、REST API コール、その他のMobile

SDK 機能を実装する基本的な方法を示します。• ネイティブ Android

アプリケーションの開発

• チュートリアル: ネイティブ AndroidWarehouse アプリケーションの作成

• Android サンプルアプリケーション

101

Android ネイティブクイックスタート

すばやく開始する手順は、次のとおりです。1. ネイティブ Android 要件をすべて満たしていることを確認します。2. Mobile SDK for Androidをインストールします。必要に応じて、代わりにMobile SDK GitHub リポジトリからMobile

SDK をインストールすることもできます。3. コマンドラインで、新しい Android プロジェクトを作成する forcedroid アプリケーションを実行し、Android

Studio またはコマンドラインからそのアプリケーションを実行します。4. 「Android Studio でのサンプルプロジェクトの設定」の手順に従います。

ネイティブ Android の要件

Mobile SDK 4.3 Android の開発には、次のソフトウェアが必要です。• Java JDK 7 以降 — www.oracle.com/downloads。• Node Package Manager (npm) — SalesforceMobileSDK-Android リポジトリへの直接アクセスを含む、すべての

Android 開発シナリオでインストールする必要があります。• Android Studio 2 以降 — developer.android.com/sdk。• Android SDK および Android SDK Tools — Android Studio 内からインストールします。

1. Android Studio メニューで、[ツール] > [Android] > [SDK Manager] をクリックします。2. [SDK Platforms] タブをクリックします。3. 少なくとも次の必須 SDK レベルとすべての中間レベルをインストールします。

– 最小限の API: Android KitKat (API 19)

– 対象の API: Android Marshmallow (API 23)

4. [SDK Tools] タブをクリックします。5. 最新バージョンの Android SDK Tools をインストールします。

• Android 仮想デバイス (AVD) — Android Studio 内からインストールします。1. Android Studio メニューで、[ツール] > [Android] > [AVD マネージャ] をクリックします。2. [仮想デバイスを作成...] をクリックします。3. Android KitKat (API 19) 以上を対象とする AVD を少なくとも 1 つインストールします。Android Studio で AVD を

設定する方法については、developer.android.com/guide/developing/devices/managing-avds.html の手順を参照してください。

Salesforce 側には、以下も必要です。• Salesforce Mobile SDK for Android 4.3 以降。「Android のインストール」を参照してください。• 接続アプリケーションが存在する Salesforce Developer Edition 組織。SalesforceSDK プロジェクトは、Android KitKat (API 19) ライブラリを使用して作成されます。

102

Android ネイティブクイックスタートネイティブ Android の開発

ヒント:

• 最良の結果を得るには、Android SDK マネージャで推奨されるすべての Android SDK バージョンと Android

SDK ツールの使用可能なすべてのバージョンをインストールします。• Windows では、必ずシステム管理者として Android Studio を実行します。• Android Studio 要件についての詳細は、developer.android.com/sdk を参照してください。

Android プロジェクトの作成

アプリケーションを作成するには、コマンドラインで forcedroid を使用します。アプリケーションを設定する方法は 2 つあります。• forcedroid アプリケーションのプロンプトで対話形式でアプリケーションオプションを設定する。• 直接コマンドラインでアプリケーションオプションを指定する。どちらの場合も、ターゲットディレクトリ設定 (--targetdir) で既存のフォルダを指し示す必要があり、そのフォルダは空になっている必要があります。ビデオチュートリアルについては、次の各ページを参照してください。• 「Installing Salesforce Mobile SDK For Android On Windows」(Windows への Salesforce Mobile SDK For Android のインストー

ル) (http://salesforce.vidyard.com/watch/LpN_y0IBjv2lOe7h7Jw9rQ)

• 「Creating Native Android Apps With Salesforce Mobile SDK」(Salesforce Mobile SDK を使用したネイティブ Android アプリケーションの作成) (http://salesforce.vidyard.com/watch/-VE6BR9V73dIrrFvIxXS-A)

プロジェクトタイプforcedroid ユーティリティによってプロジェクトタイプを選択するように求められます。プロジェクトタイプオプションにより、最も生産性の高い開発環境で Mobile SDK を使用するための柔軟性を得られます。

言語アーキテクチャアプリケーション種別

Javaネイティブnative

JavaScript with ReactReact Nativereact_native

JavaScript、CSS、HTML5ハイブリッドhybrid_local

JavaScript、CSS、HTML5、ApexVisualforce を使用するハイブリッドhybrid_remote

ネイティブ Android アプリケーションを作成するには、native を指定します。

対話形式でのアプリケーションオプションの指定対話形式でアプリケーションオプションを入力するには、「forcedroid create」と入力します。forcedroid ユーティリティにより、各設定オプションが表示されます。

103

Android プロジェクトの作成ネイティブ Android の開発

アプリケーションオプションの直接指定必要に応じて、コマンドラインから直接 forcedroid パラメータを指定できます。使用方法に関する情報を表示するには、引数を指定せずに「forcedroid」と入力します。次のように使用可能なオプションのリストが表示されます。$ forcedroidUsage:forcedroid create

--apptype=<Application Type> (native, react_native, hybrid_remote, hybrid_local)--appname=<Application Name>--targetdir=<Target App Folder> <must be an existing folder>--packagename=<App Package Identifier> (com.my_company.my_app)--startpage=<Path to the remote start page> (/apex/MyPage —

Only required/used for 'hybrid_remote')[--usesmartstore=<Whether or not to use SmartStore/SmartSync> ('yes' or 'no',

‘no’ by default -- Only required/used for ‘native’)]

この情報を使用して、「forcedroid create」と入力してからオプションおよび値を入力します。次に例を示します。$ forcedroid create --apptype="native" --appname="packagetest" --targetdir="PackageTest"--packagename="com.test.my_new_app"

Android Studio でのアプリケーションのインポートおよび作成1. Android Studio でプロジェクトを開きます。

• ようこそ画面から [Import Project (Eclipse ADT, Gradle, etc.) (プロジェクトをインポート (Eclipse ADT、Gradle

など))] をクリックします。または

• [File (ファイル)] メニューから、[File (ファイル)] > [New (新規)] > [Import Project... (プロジェクトをインポート...)] をクリックします。

2. プロジェクトのディレクトリを参照し、[OK] をクリックします。• ネイティブプロジェクトの場合、ターゲットディレクトリを選択します。• ハイブリッドプロジェクトの場合、<your_target_directory>/platforms/androidを選択します。Android Studio によってワークスペースが自動的に作成されます。このプロセスに数分かかることがあります。ステータスバーに「Gradle build successful (Gradle のビルドに成功しました)」と表示されていれば、プロジェクトを実行できます。

3. [Run <project_name> (<project_name> を実行)] をクリックするか、SHIFT+F10 キーを押します。ネイティブプロジェクトの場合、プロジェクト名は指定したアプリケーション名になります。ハイブリッドプロジェクトの場合は、「android」になります。Android Studio によってエミュレータまたは接続されている Android デバイスにアプリケーションが起動します。

104

Android プロジェクトの作成ネイティブ Android の開発

コマンドラインからのアプリケーションの作成および実行コマンドラインからコマンドプロンプトに戻ると、プロジェクトを設定およびクリーンアップするためのAndroid ユーティリティの実行手順が forcedroid スクリプトにより出力されます。コマンドラインからアプリケーションを作成および実行する場合は、これらの手順を実行します。1. 新しいアプリケーションを作成します。

• Windows:

cd <your_project_directory>gradlew assembleDebug

• Mac:

cd <your_project_directory>./gradlew assembleDebug

正常に作成されると、プロジェクトの build/outputs/apk ディレクトリに署名付き APK デバッグファイルを検索できます。

2. エミュレータが実行されていない場合は、Android AVD マネージャを使用して起動します。物理デバイスを使用している場合は、接続します。

3. APK ファイルをエミュレータまたはデバイスにインストールします。• Windows:

adb install <path_to_your_app>\build\outputs\apk\<app_name>.apk

• Mac:

./adb install <path_to_your_app>/build/outputs/apk/<app_name>.apk

新しくインストールされたアプリケーションがない場合は、エミュレータまたはデバイスを再起動します。詳細は、developer.android.comの「Building and Running from the Command Line」(コマンドラインからの作成および実行)

を参照してください。

関連トピック:

forcedroid パラメータforcedroid パラメータ

Android Studio でのサンプルプロジェクトの設定

SalesforceMobileSDK-Android GitHub リポジトリには、作成して実行できるサンプルアプリケーションが含まれています。1. SalesforceMobileSDK-Android GitHub リポジトリをまだコピーしていない場合は、コピーします。

105

Android Studio でのサンプルプロジェクトの設定ネイティブ Android の開発

Mac:

git clone https://github.com/forcedotcom/SalesforceMobileSDK-Android.git./install.sh

• Windows:

git clone https://github.com/forcedotcom/SalesforceMobileSDK-Android.gitcscript install.vbs

2. Android Studio でプロジェクトを開きます。• ようこそ画面から [Import Project (Eclipse ADT, Gradle, etc.) (プロジェクトをインポート (Eclipse ADT、Gradle

など))] をクリックします。または

• [File (ファイル)] メニューから、[File (ファイル)] > [New (新規)] > [Import Project... (プロジェクトをインポート...)] をクリックします。

3. <path_to_SalesforceMobileSDK-Android>/native/NativeSampleApps/ または<path_to_SalesforceMobileSDK-Android>/hybrid/HybridSampleApps/ を参照します。

4. リストされているサンプルアプリケーションのいずれかを選択し、[OK] をクリックします。5. プロジェクトの作成が終了したら、[Select Run/Debug Configurations (実行/デバッグ設定の選択)] ドロップダウ

ンメニューでサンプルプロジェクトを選択します。6. SHIFT-F10 キーを押します。

Android プロジェクトファイルネイティブプロジェクトの forcedroid ディレクトリには、次のライブラリプロジェクトがあります。• libs/SalesforceSDK — Salesforce Mobile SDKプロジェクト。OAuth2 および REST API コールのサポートを提供

します。• libs/SmartStore — SmartStore プロジェクト。オフラインストレージソリューションを提供します。• libs/SmartSync — SmartSync プロジェクト。オフラインデータ同期ツールを実装します。• external/sqlcipher — サードパーティ SQLCipher ライブラリ。SmartStore で使用される暗号化ツールを提

供します。Mobile SDK の各ライブラリは、次の図で示すように連動関係階層で相互に参照し合います。

106

Android プロジェクトファイルネイティブ Android の開発

ネイティブ Android アプリケーションの開発

Salesforce Mobile SDKのネイティブ Android バージョンでは、ホストデバイスの Android オペレーティングシステムを直接使用するリッチモバイルアプリケーションを作成できます。このようなアプリケーションを作成するには、Java および Android 開発を十分に理解し、Mobile SDK ネイティブクラスを使用するコードを記述できる必要があります。

Android アプリケーションの構造通常、Mobile SDKを使用するネイティブ Android アプリケーションには、次のクラスとアクティビティが必要になります。• android.app.Application を拡張するアプリケーションエントリポイントクラス• android.app.Activity を拡張する 1 つ以上のアクティビティMobile SDK では、次の作業を実行します。• android.app.Application を拡張するスタブクラスを作成する。• onCreate() を Application スタブクラスに実装して SalesforceSDKManager.initNative() をコー

ルする。

107

ネイティブ Android アプリケーションの開発ネイティブ Android の開発

• SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivityを拡張する。この拡張は省略可能ですが、実行することをお勧めします。

最上位レベルの SalesforceSDKManagerクラスは、パスコードを使用するアプリケーションにはパスコード機能を実装し、パスコードを使用しないアプリケーションには空白を入力します。また、ログインのフェーズを設定したり、ログアウト後にクリーンアップしたり、システムレベルアカウントが削除されたときにアプリケーションに情報を通知する特殊なイベントウォッチャを提供したりします。OAuth プロトコルは、内部クラスで自動的に処理されます。SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivity クラスは、アプリケーションの一時停止および再開イベントや関連するパスコード管理を自由に処理できます。アプリケーションのメインアクティビティだけでなくすべてのアクティビティで、これらのいずれかのクラスを拡張することをお勧めします。アクティビティで別の基本クラスを使用する場合、SalesforceActivity にある一時停止および再開プロトコルを自分で置き換える必要があります。アクティビティ内で、Salesforce REST API をコールして Salesforce オブジェクトを操作します。Mobile SDKには、REST

要求および応答フローを簡略化する com.salesforce.androidsdk.restパッケージが用意されています。ユーザインターフェースレイアウト、画像サイズ、文字列、および XML ファイルのその他のリソースを定義してカスタマイズします。SDK は、内部的に Rクラスインスタンスを使用して、リソースを取得および操作します。ただし、クライアントアプリケーションは Mobile SDK のリソースに直接アクセスできるため、これらの機能を管理するためにコードを記述する必要はありません。

108

Android アプリケーションの構造ネイティブ Android の開発

ネイティブ API パッケージSalesforce Mobile SDK では、ネイティブ Android API が Java パッケージにグループ化されています。これらのパッケージの概要と要点については、「Android パッケージおよびクラス」を参照してください。

ネイティブクラスの概要この Mobile SDK ネイティブクラスの概要では、各クラスの関連する詳細や必要なクラスがどこにあるのかについて説明します。

SalesforceSDKManager クラスSalesforceSDKManagerクラスは、Salesforce Mobile SDKを使用するすべてのネイティブ Android アプリケーションのエントリポイントです。このクラスは次のメカニズムを提供します。

109

ネイティブ API パッケージネイティブ Android の開発

• ログインおよびログアウト• パスコード• ユーザデータの暗号化および復号化• 文字列変換• ユーザエージェントアクセス• アプリケーションの終了• アプリケーションのクリーンアップ

initNative() メソッド起動時に、静的 initNative() メソッドをコールして、シングルトン SalesforceSDKManager オブジェクトを初期化します。このメソッドには次の 4 つの引数があります。

説明パラメータ名

アプリケーションのコンテキストを説明する Contextのインスタンス。Application 拡張クラスでは、コールを

applicationContext

getApplicationContext() に渡してこのパラメータを満たすことができます。

KeyInterface Mobile SDK インターフェースの実装のインスタンス。このインターフェースを実装する必要があります。

keyImplementation

メインアクティビティを表示するクラスの記述子。メインアクティビティは、ログイン後に最初に表示されるアクティビティです。

mainActivity

(省略可能) カスタム LoginActivity クラスのクラス記述子。loginActivity

次に、TemplateApp の例を示します。SalesforceSDKManager.initNative(getApplicationContext(), new KeyImpl(), MainActivity.class);

この例では、KeyImpl は、KeyInterface のアプリケーションの実装です。MainActivity は、SalesforceActivity をサブクラス化し、ここではログイン後に最初にコールされるアクティビティとして指定されています。

logout() メソッドSalesforceSDKManager.logout()メソッドは、ユーザデータをクリアします。たとえば、ユーザ固有の独自リソースを取り入れたが、次のユーザセッションには保持したくないとします。SmartStore は、ログアウト時にユーザデータおよびアカウント情報を自動的に破棄します。

110

ネイティブクラスの概要ネイティブ Android の開発

クリーンアップ後 (推奨) に、メソッド上書きのどこかでスーパークラスメソッドを常にコールします。次に、擬似コード例を示します。@Overridepublic void logout(Activity frontActivity) {

// Clean up all persistent and non-persistent app artifacts// Call superclass after doing your own cleanupsuper.logout(frontActivity);

}

getLoginActivityClass() メソッドこのメソッドは、ログインアクティビティの記述子を返します。ログインアクティビティは、Salesforce サーバがログインダイアログを提供するために使用する WebView を定義します。

getUserAgent() メソッドMobile SDK は、実行時にアプリケーションのバージョン設定情報を公開するためのユーザエージェント文字列を作成します。このユーザエージェントの形式は次のようになります。SalesforceMobileSDK/<salesforceSDK version> android/<android OS version> appName/appVersion<Native|Hybrid>

次に、実際の例を示します。SalesforceMobileSDK/2.0 android mobile/4.2 RestExplorer/1.0 Native

実行時にユーザエージェントを取得するには、SalesforceSDKManager.getUserAgent() メソッドをコールします。

isHybrid() メソッドMobile SDK アプリケーションで、ネイティブクライアントとハイブリッドクライアントの両方を提供するように設計されたライブラリを作成するとします。コールするアプリケーションのタイプに応じてライブラリコードが内部的に切り替わりますが、実行時に何らかの方法でアプリケーションタイプを判断する必要があります。コードでコール元アプリケーションタイプを判断するには、boolean 型のSalesforceSDKManager.isHybrid() メソッドをコールします。true はハイブリッド、false はネイティブを意味します。

KeyInterface インターフェースKeyInterface は、実装して SalesforceSDKManager.initNative() メソッドに渡す必須のインターフェースです。

getKey() メソッドBase64 でエンコードされた暗号化キーを getKey()抽象メソッドから返す必要があります。Encryptor.hash()

および Encryptor.isBase64Encoded()ヘルパーメソッドを使用して、適切なキーを生成します。Mobile SDK

は、キーを使用してアプリケーションデータおよびアカウント情報を暗号化します。

111

ネイティブクラスの概要ネイティブ Android の開発

PasscodeManager クラスPasscodeManagerクラスは、パスコードの暗号化を管理し、必要に応じてパスコードページを表示します。また、モバイルポリシーを読み込み、ローカルにキャッシュします。このクラスはすべてのパスコード関連のアクティビティを処理するために内部的に使用されます。これにより、ユーザのコーディングは最小限に抑えられます。一般的に、アプリケーションは次の 3 つの PasscodeManager メソッドのみをコールします。• public void onPause(Activity ctx)

• public boolean onResume(Activity ctx)

• public void recordUserInteraction()

これらのメソッドは、次の要件を満たすネイティブアクティビティクラスでコールされる必要があります。• パスコードを必要とするアプリケーション内に存在している。• SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivityを拡張し

ない。SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivity を拡張する任意のアクティビティでこの実装を自由に取得できます。

onPause() および onResume()

これらのメソッドは、ユーザがアプリケーションを一時停止および再開したときのパスコードのダイアログボックスを処理します。アクティビティクラスの一致するメソッドでこれらの各メソッドをコールします。たとえば、SalesforceActivity.onPause() は、スーパークラスをコールする前にクラス記述子を引数として渡し、PasscodeManager.onPause() をコールします。@Overridepublic void onPause() {

passcodeManager.onPause(this);super.onPause();

}

PasscodeManager.onResume() メソッドの boolean 型の戻り値を他のアクションを再開するための条件として使用します。アプリケーションの onResume() の実装では、PasscodeManager バージョンをコールする前にスーパークラスメソッドをコールします。次に例を示します。@Overridepublic void onResume() {

super.onResume();// Bring up passcode screen if neededpasscodeManager.onResume(this);

}

recordUserInteraction()

このメソッドは、最近のユーザ操作の大部分のタイムスタンプを保存します。アクティビティのonUserInteraction() メソッドで PasscodeManager.recordUserInteraction() をコールします。次に例を示します。@Overridepublic void onUserInteraction() {

112

ネイティブクラスの概要ネイティブ Android の開発

passcodeManager.recordUserInteraction();}

Encryptor クラスEncryptor ヘルパークラスは、SDK で必要なハッシュを使用して文字列の暗号化および復号化を行う静的ヘルパーメソッドを提供します。Mobile SDK で使用されるすべてのキーは Base64 でエンコードされている必要があるとうことを、ネイティブアプリケーションが認識していることが重要です。他の暗号化パターンは使用できません。ハッシュを作成して、正しいエンコードを使用していることを確認する場合は、Encryptor クラスを使用します。大部分の Encryptorメソッドは内部で使用されますが、このユーティリティは必要に応じてアプリケーションで自由に使用できます。たとえば、アプリケーションで独自のデータベースを実装する場合、制限のない暗号化および復号化ツールとして Encryptor を使用できます。

SalesforceActivity クラス、SalesforceListActivity クラス、およびSalesforceExpandableListActivity クラスSalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivityは、ネイティブ SDK アクティビティの骨組みとなる基本クラスです。これらは、それぞれ android.app.Activity、android.app.ListActivity、android.app.ExpandableListActivity を拡張します。これらの各クラスでは、PasscodeManagerコールを自由に実装できます。アプリケーションでパスコードを現在使用していない場合でも、可能であればすべてのアプリケーションのアクティビティでこれらのいずれかのクラスを拡張することをお勧めします。パスコードで保護されているアプリケーションの場合:いずれかのアクティビティで SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivity を拡張していない場合、これらの各アクティビティにパスコードプロトコルを少し追加する必要があります。「パスコードの使用」を参照してください。これらの各アクティビティクラスには、次の 1 つの抽象メソッドが含まれています。public abstract void onResume(RestClient client);

このメソッドは、クラスによって実装される Activity.onResume() メソッドをオーバーロードします。クラスメソッドは、RestClientインスタンスをインスタンス化した後でオーバーロードをコールします。このメソッドを使用して、渡されるクライアントをキャッシュし、そのクライアントを使用して REST 要求を実行します。

UI クラスcom.salesforce.androidsdk.uiパッケージのアクティビティは、すべての Mobile SDK アプリケーションに共通する UI リソースを表しています。XML を介して、これらのリソースのスタイル、スキン、テーマを設定したり、カスタマイズしたりできます。SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivity を除き、実行時にリソースを置き換えることを目的として、これらのアクティビティクラスを上書きしないでください。

113

ネイティブクラスの概要ネイティブ Android の開発

ClientManager クラスClientManager は、Android AccountManager クラスと連動して、ユーザアカウントを管理します。アプリケーションにとって特に重要なことは、ClientManager クラスが次の 2 つのメソッドを介して RestClient インスタンスへのアクセスを提供するという点です。• getRestClient()

• peekRestClient()

getRestClient()メソッドは、Salesforce データをクエリするための RestClientインスタンスを非同期で作成します。この場合、非同期とは、このメソッドが UI スレッドでの使用を目的としていることを意味します。peekRestClient() メソッドは、UI 以外のコンテキストで使用する RestClient インスタンスを同期して作成します。RestClient インスタンスを取得したら、このインスタンスを使用して、REST API コールを Salesforce に送信できます。

RestClient クラス名前が示すように、RestClientクラスは、Android アプリケーションとSalesforce REST API の連絡役になります。RestClientクラスの新しいインスタンスは明示的に作成しません。代わりに、ClientManagerファクトリクラスを使用して、RestClientインスタンスを取得します。RestClientインスタンスを取得したら、このインスタンスを使用して、REST API コールを Salesforce に送信できます。コールするメソッドは、UI コンテキストからコールするかどうかによって異なります。「ClientManager クラス」を参照してください。次の RestClient メソッドを使用して、REST 要求を送信します。• sendAsync() — ClientManager.getRestClient() をコールして RestClient インスタンスを取得し

た場合、このメソッドをコールします。• sendSync() — ClientManager.peekRestClient() をコールして RestClient インスタンスを取得し

た場合、このメソッドをコールします。

sendSync() メソッド要求に対してどの程度の情報を提供できるかに応じて、RestClient.sendSync() の 3 つのオーバーロードから選択できます。

sendAsync() メソッドRestClient.sendAsync() メソッドは、WrappedRestRequest の新しいインスタンスの RestRequest オブジェクトをラップします。次に、WrappedRestRequest オブジェクトを要求キューに追加して、そのオブジェクトを返します。待機中に要求をキャンセルする場合、WrappedRestRequestオブジェクトで cancel()

をコールします。

getRequestQueue() メソッド基盤となる RequestQueue オブジェクトにアクセスするには、RestClient インスタンスでrestClient.getRequestQueue() をコールします。RequestQueue オブジェクトを使用すると、待機中の要求を直接キャンセルまたは操作できます。たとえば、restClient.getRequestQueue().cancelAll()

114

ネイティブクラスの概要ネイティブ Android の開発

をコールして待機中の要求キュー全体をキャンセルできます。「要求キューの管理」のコード例を参照してください。

RestRequest クラスRestRequest クラスは、アプリケーションから提供されるデータに基づいて REST API 要求を作成および書式設定します。これは、Mobile SDK によって実装され、自身のインスタンスのファクトリとして機能します。RestRequest のインスタンスを直接作成しないでください。代わりに、適切な RestRequest の静的ファクトリメソッド (RestRequest.getRequestForCreate()など) をコールします。要求を送信するには、返された RestRequest オブジェクトを RestClient.sendAsync() または RestClient.sendSync() に渡します。「REST API の使用」を参照してください。RestRequest クラスは、Salesforce REST API および SOAP API によって提供される標準の Salesforce データ操作をネイティブに処理します。サポートされる操作は次のとおりです。

説明パラメータ操作

Salesforceバージョンのメタデータを返します。

なしVersions

リソース名および URI を含む、指定された API バージョンで使用可能なリソースを返します。

API バージョンResources

オブジェクトの完全なメタデータコレクションを返します。

API バージョン、オブジェクト種別Metadata

組織で使用できるすべてのオブジェクトとそのメタデータのリストを返します。

API バージョンDescribeGlobal

1 つのオブジェクト種別の説明を返します。

API バージョン、オブジェクト種別Describe

指定したオブジェクトに新しいレコードを作成します。

API バージョン、オブジェクト種別、値オブジェクトに対する項目名の対応付け

Create

オブジェクト ID でレコードを取得します。

API バージョン、オブジェクト種別、オブジェクト ID、項目のリスト

Retrieve

指定された SOQL 検索を実行します。

API バージョン、SOQL クエリ文字列Search

指定されたオブジェクトの検索結果レイアウト情報を返します。

API バージョン、オブジェクトのリスト

SearchResultLayout

ログインユーザのデフォルトのグローバル検索範囲内にあるオブジェクトの順序付きリストを返します。

API バージョンSearchScopeAndOrder

115

ネイティブクラスの概要ネイティブ Android の開発

説明パラメータ操作

指定された対応付けでオブジェクトを更新します。

API バージョン、オブジェクト種別、オブジェクト ID、値オブジェクトに対する項目名の対応付け

Update

外部 ID が外部 ID 項目に現在存在しているかどうかに基づいて、外部

API バージョン、オブジェクト種別、外部 ID 項目、外部 ID、値オブ

Upsert

データからオブジェクトを更新または挿入します。

ジェクトに対する項目名の対応付け

指定された ID を持つ特定のタイプのオブジェクトを削除します。

API バージョン、オブジェクト種別、オブジェクト ID

Delete

適切な RestRequestインスタンスを取得するには、実行する操作に一致する RestRequest静的メソッドをコールします。次に、RestRequest 静的メソッドを示します。• getRequestForCreate()

• getRequestForDelete()

• getRequestForDescribe()

• getRequestForDescribeGlobal()

• getRequestForMetadata()

• getRequestForQuery()

• getRequestForResources()

• getRequestForRetrieve()

• getRequestForSearch()

• getRequestForSearchResultLayout()

• getRequestForSearchScopeAndOrder()

• getRequestForUpdate()

• getRequestForUpsert()

• getRequestForVersions()

これらのメソッドは、RestClientのインスタンスに渡す RestRequestオブジェクトを返します。RestClient

クラスは、要求を送信する同期メソッド (sendSync()) および非同期メソッド (sendAsync()) を提供します。UI スレッドから要求を送信する場合は、sendAsync() を使用します。 sendSync() は、非 UI スレッド (アクティビティによって実行されるサービスまたはワーカースレッドなど) の場合にのみ使用します。

FileRequests クラスFileRequests クラスは、ファイル操作要求を構築するメソッドを提供します。各メソッドは、新しいRestRequestオブジェクトを返します。アプリケーションは、このオブジェクトを Salesforce サービスに送信して要求を処理します。たとえば、次のコードスニペットは ownedFilesList() メソッドをコールして

116

ネイティブクラスの概要ネイティブ Android の開発

RestRequest オブジェクトを取得します。次に、RestClient.sendAsync() を使用して RestRequest オブジェクトをサーバに送信します。RestRequest ownedFilesRequest = FileRequests.ownedFilesList(null, null);RestClient client = this.client;client.sendAsync(ownedFilesRequest, new AsyncRequestCallback() {

// Do something with the response});

メモ: この例では、null を最初のパラメータ (userId) に渡します。この値で、コンテキスト (ログインしている) ユーザの ID を使用するように ownedFilesList() メソッドに指示します。pageNum パラメータの 2 番目の null で、結果の最初のページを取得するようにメソッドに指示します。

FileRequests メソッドについての詳細は、「ファイルとネットワーキング」を参照してください。

メソッドFileRequests メソッドについての詳細は、「FileRequests メソッド (Android)」を参照してください。REST リクエストボディおよびレスポンスボディについての詳細は、[Chatter REST API Resources (Chatter REST API リソース)] > [Files Resources (ファイルリソース)] (http://www.salesforce.com/us/developer/docs/chatterapi) を参照してください。

説明メソッド名

指定されたユーザが所有するファイルのリストからページを取得する要求を構築します。

ownedFilesList

ユーザのグループが所有するファイルのリストからページを取得する要求を構築します。

filesInUsersGroups

ユーザと共有しているファイルのリストからページを取得する要求を構築します。

filesSharedWithUser

特定のバージョンのファイルの詳細を取得する要求を構築します。

fileDetails

1 つの要求で 1 つ以上のファイルの最新の詳細を取得する要求を構築します。

batchFileDetails

ファイル (およびバージョン) の特定のページのプレビュー/変換を取得する要求を構築します。

fileRendition

この特定のファイルの実際のバイナリコンテンツを取得する要求を構築します。

fileContents

このファイルの共有先のエンティティのリストからページを取得する要求を構築します。

fileShares

指定されたファイル ID のファイル共有を指定されたエンティティ ID に追加する要求を構築します。

addFileShare

指定されたファイル共有を削除する要求を構築します。deleteFileShare

117

ネイティブクラスの概要ネイティブ Android の開発

説明メソッド名

新しいファイルをサーバにアップロードする要求を構築します。新しいファイルを作成します。

uploadFile

OkHttp: 基盤となるネットワークライブラリMobile SDK 4.2 以降では、Android REST 要求システムは、基盤となるアーキテクチャとして Square Open Source のオープンソース外部ライブラリの OkHttp (v3.2.0) を使用します。過去のリリースの Google Volley ライブラリは、このライブラリに置き換えられます。そのため、Mobile SDK では、WrappedRestRequestクラスが定義されなくなりました。

例: 次の例に、OkHttpClientを使用したいくつかの一般的なネットワーク操作の実行方法を示します。一般的なインポート

import okhttp3.Headers;

import okhttp3.HttpUrl;

import okhttp3.OkHttpClient;

import okhttp3.Call;

import okhttp3.Dispatcher;

import okhttp3.Request;

import okhttp3.RequestBody;

import okhttp3.Response;

現在の OkHttp クライアントハンドルを取得する現在の RestClient インスタンスが使用している OkHttpClient のハンドルを取得するには、次のように指定します。

OkHttpClient okClient = restClient.getOkHttpClient();

OkHttp ディスパッチャを取得する

Dispatcher dispatcher = restClient.getOkHttpClient().dispatcher();

待機中のすべてのコールをキャンセルする

Dispatcher dispatcher = restClient.getOkHttpClient().dispatcher();

dispatcher.cancelAll();

OkHttp ハンドルを REST 要求に格納する

Call call = restClient.sendAsync(restRequest, callback);

格納されたハンドルを使用して特定の REST 要求をキャンセルする

Call call = restClient.sendAsync(restRequest, callback);

...

call.cancel();

詳細は、square.github.io/okhttp/を参照してください。

118

ネイティブクラスの概要ネイティブ Android の開発

LoginActivity クラスLoginActivityは、ログイン画面を定義します。ログインワークフローについては、説明する価値があります。それは、ログインワークフローでアクティビティパッケージの他の 2 つのクラスが説明されているからです。ログインアクティビティで、[Menu (メニュー)] ボタンを押すと、[Clear Cookies (クッキーを解除)]、[Reload

(再読み込み)]、[Pick Server (サーバを選択)]の 3 つのオプションが表示されます。[Pick Server (サーバを選択)]は、[Production (本番)]、[Sandbox]、[Custom Server (カスタムサーバ)]オプションを表示する ServerPickerActivity

クラスのインスタンスを起動します。[Custom Server (カスタムサーバ)]を選択すると、ServerPickerActivity

は CustomServerURLEditor クラスのインスタンスを起動します。このクラスは、カスタムサーバの名前を入力できるポップオーバーダイアログを表示します。

その他の UI クラスuiパッケージにあるその他のいくつかのクラスは、ネイティブ API 開発作業には影響しませんが、重要なためここで説明します。PasscodeActivity クラスは、パスコード画面の UI を提供します。これは、Create、CreateConfirm、Check の 3

つのモードのいずれかで実行されます。ユーザが最初にログインしようとしたときは Create モードになります。ここで、ユーザはパスコードを作成するように要求されます。ユーザがパスコードを送信すると、画面がCreateConfirm モードで返され、ユーザは新しいパスコードを確認するように要求されます。以降は、ユーザにパスコードの入力を要求する Check モードの画面が表示されるようになります。SalesforceR は、非推奨クラスです。Mobile SDK が JAR 形式で提供されていたときは、開発者がバイナリファイルのリソースを編集するためにこのクラスが必要でした。Mobile SDK は、ライブラリプロジェクトとして使用できるようになったため、SalesforceRは必要なくなりました。代わりに、SDK のリソースを自分のリソースで上書きできます。SalesforceDroidGapActivityおよび SalesforceGapViewClientは、ハイブリッドアプリケーションでのみ使用します。

UpgradeManager クラスUpgradeManager は、デバイスにインストールされている SDK バージョンをサイレントアップグレードするメカニズムを提供します。このクラスは、デバイスの共有設定ファイルに SDK バージョン情報を保存します。アップグレードを実行するために、UpgradeManager は、現在の SalesforceSDKManager インスタンスをクエリしてその SDK バージョンを取得し、デバイスのバージョン情報と比較します。アップグレードが必要な場合 (データベーススキーマや暗号化パターンに変更がある場合など)、UpgradeManager は、デバイスの SDK

コンポーネントをアップグレードするために必要な手順を実行できます。このクラスは、将来使用される予定です。Mobile SDK 2.0 の実装では、単にバージョン文字列を保存して比較するだけです。

ユーティリティクラスutil パッケージの大部分のクラスは内部で使用されますが、いくつかのクラスはサードパーティ開発者にも利点があります。

119

ネイティブクラスの概要ネイティブ Android の開発

説明クラス

Mobile SDK for Android が伝搬するすべてのイベントのリストは、ソースコードを参照してください。

EventsObservable

イベントを傍受するにはこのインターフェースを実装します。この機能は、特定のタイプのイベント発生時に特殊な操作を実行する場合に便利です。

EventsObserver

この静的ヘルパークラスは直接コールできます。このクラスは、特定の URI を解析して、そのパラメータを一連のキー/値ペアに分離し、対応付けで返します。

UriFragmentParser

ForcePlugin クラスcom.salesforce.androidsdk.phonegapパッケージのすべてのクラスは、ハイブリッドアプリケーションのサポートを目的としています。これらのクラスの大部分には、ネイティブコードにアクセスする Javascript プラグインが実装されています。これらの Mobile SDK プラグインの基本クラスは ForcePlugin です。Mobile SDK

アプリケーションに独自の Javascript プラグインを実装する場合、ForcePluginを拡張して、抽象 execute()

関数を実装します。ForcePluginは、Javascript フレームワークと連動する CordovaPluginを拡張します。これにより、ネイティブ関数をコールできる Javascript モジュールを作成できるようになります。PhoneGap は両方のブリッジになります。CordovaPlugin でネイティブプラグインを作成し、それを複製する Javascript ファイルを作成します。Cordova は、いずれかのプラグインの Javascript 関数をスクリプトでコールすると、プラグインの execute()関数をコールします。

パスコードの使用Mobile SDKアプリケーションのユーザデータは暗号化で保護されます。Salesforce 組織のシステム管理者は、ユーザに接続アプリケーションのパスコードを入力するように要求できます。この場合、アプリケーションは暗号化ハッシュキーとしてそのパスコードを使用します。Salesforce システム管理者がパスコードを要求しない場合、独自のキーを自分で入力する必要があります。Salesforce Mobile SDK は、パスコードワークフローのすべての実装作業を行うわけではありません。パスコードマネージャをコールしてユーザ入力を取得し、パスコードとプレフィックス/サフィックスを組み合わせて、ユーザデータを暗号化するためのハッシュを作成します。また、パスコードが変更されたときのデータの復号化と再暗号化を処理します。組織がパスコード要件を変更した場合、Mobile SDK は次のログインで変更を検出し、その変更に応じて対応します。パスコードを使用する場合、SalesforceSDKManager.getKey()メソッドを実装するだけで済みます。この場合、実装で行うべきことは、暗号化キーとして使用できる Base64 エンコード文字列を返すことだけです。パスコードは内部的に Base64 エンコード文字列として保存されます。SDK は、Encryptorクラスを使用して、パスコードからハッシュを作成します。また、パスコードの代わりにキーを入力する場合も、このクラスを使用してハッシュを生成する必要があります。パスコードとキーは、SmartStoreデータ、oAuth トークン、ユーザID 文字列、関連するセキュリティ情報を暗号化および復号化する場合に使用されます。パスコードで暗号化さ

120

パスコードの使用ネイティブ Android の開発

れるセキュリティデータを詳しく確認するには、ClientManager.changePasscode() メソッドを参照します。モバイルポリシーは、特定のパスコード属性 (パスコードの長さやパスコードダイアログ表示のタイミングなど) を定義します。接続アプリケーションのモバイルポリシーファイルは、Salesforce サーバにあります。ユーザが正しくないパスコードを 10 回連続で入力すると、そのユーザはログアウトされます。Mobile SDK は、ユーザが正しくないパスコードを入力した場合にフィードバックを提供し、試行できる残りの回数をユーザに通知します。PasscodeManagerクラスは、画面がロックされる前にフロントアクティビティへの参照を保存し、画面のロックが解除されたときに同じアクティビティを再開できるようにします。パスコードで保護されたアプリケーションで SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivity を拡張しないアクティビティを定義する場合、これらの各アクティビティクラスから次の 3 つの PasscodeManager メソッドをコールしてください。• PasscodeManager.onPause()

• PasscodeManager.onResume(Activity)

• PasscodeManager.recordUserInteraction()

同じ名前のアクティビティのメソッドから onPause()および onResume()をコールします。アクティビティの onUserInteraction() メソッドから recordUserInteraction() をコールします。アクティビティクラス記述子を onResume() に渡します。これらのコールにより、このようなイベント時にアプリケーションでパスコードセキュリティが適用されます。「PasscodeManager クラス」を参照してください。

メモ: SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivity

クラスには、これらの必須メソッドを無償で実装できます。可能な場合は、これらのいずれかのクラスに基づいてアクティビティクラスを作成してください。

リソースの処理Salesforce Mobile SDK リソースは、libs/SalesforceSDK/res フォルダにある XML ファイルで設定されています。これらのリソースの多くは、このフォルダで変更することでカスタマイズできます。/res フォルダのリソースは、次のようなカテゴリに分類されます。• Drawables — 背景、影付き、画像リソース (PNG ファイルなど)

• Layouts — 可視コンポーネント (パスコード画面など) の画面設定• Values — SDK で使用される文字列、色、サイズその他の 2 つのリソース種別は、ほとんど内部で使用されます。• Menu

• XML

drawable、layout、および value リソースは、さまざまなフォーム要素に対応するフォルダにさらに分類されます。これらのカテゴリは、各種デバイス種別および画面解像度に対応します。各カテゴリはそのフォルダ名で定義されるため、すべてのバージョンで同じリソースファイル名を使用できます。たとえば、開発者がicon1.pngという名前のアイコンをさまざまなサイズで提供する場合、スマートフォン、ローエンドフォン、タブレットに対応する各フォルダにアイコンを配置します。各フォルダで、このファイル名は icon1.pngになります。フォルダ名の語幹は同じですが、サフィックスが異なります。次の表に、フォルダ名とサフィックスを示します。

121

リソースの処理ネイティブ Android の開発

使用方法フォルダ名

描画可能リソースの汎用バージョンdrawable

高解像度 (スマートフォン向け)drawable-hdpi

低解像度 (ローエンド機能端末向け)drawable-ldpi

中解像度 (ローエンド機能スマートフォン)drawable-mdpi

超高密度画面 (~ 320 dpi) のリソースdrawable-xhdpi

タブレット画面 (横方向)drawable-xlarge

タブレット画面 (縦方向)drawable-xlarge-port

超超高密度画面 (~ 480 dpi) のリソースdrawable-xxhdpi-port

レイアウトの汎用バージョンlayout

[接続を追加] ダイアログおよび電話のログインメニューmenus

汎用スタイルおよび値values

一般的なアプリケーション設定xml

コンパイラは、ターゲットデバイス設定に一致する名前のフォルダでリソースを検索します。要求されたリソースが想定されるフォルダにない場合 (ターゲットデバイスはタブレットであるが、要求されたアイコンがdrawables-xlargeまたは drawables-xlarge-portフォルダにない場合など)、コンパイラは汎用 drawable

フォルダでアイコンファイルを検索します。

LayoutsMobile SDK の Layouts は、すべてのアプリケーションが使用する画面リソースを指定します。たとえば、Layouts

は、ログインおよびパスコードを処理するダイアログボックスを設定します。layout の XML ノードの名前は、レイアウトが指定するコントロールのタイプを示します。たとえば、res/layout/sf__passcode.xml にある次の EditText ノードは、テキスト編集コントロールを指定します。

<EditText android:id="@+id/sf__passcode_text"style="@style/SalesforceSDK.Passcode.Text.Entry"android:inputType="textPassword" />

この場合、EditText コントロールは android:inputType 属性を使用します。その値が「textPassword」となっているため、オペレーティングシステムで入力値が隠されます。style 属性は、リソースの他の場所で定義されたグローバルスタイルを参照します。所定の場所で style 属性を指定する代わりに、中央ファイルでスタイルを定義し、必要な場所でその属性を参照します。値

122

リソースの処理ネイティブ Android の開発

@style/SalesforceSDK.Passcode.Text.Entry は、res/values/sf__styles.xml で定義された SDK 所有のスタイルを参照します。次に、スタイルの定義を示します。<style name="SalesforceSDK.Passcode.Text.Entry">

<item name="android:layout_width">wrap_content</item><item name="android:lines">1</item><item name="android:maxLength">10</item><item name="android:minWidth">

@dimen/sf__passcode_text_min_width</item><item name="android:imeOptions">actionGo</item>

</style>

いずれかの独自のスタイルへの参照で style 属性を上書きできます。sf__styles.xml を変更する代わりに、xyzcorp__styles.xml などの別ファイルでスタイルを定義します。res/values フォルダ (汎用デバイススタイル) または res/values-xlarge フォルダ (タブレットデバイス) にファイルを配置します。

Valuesres/values および res/values-xlarge フォルダには、サイズ、色、文字列のリソースやカスタムスタイルなどのスタイルコンポーネントの定義が含まれています。このフォルダのファイル名は、リソースまたはスタイルコンポーネントのタイプを示します。独自の値を提供するには、会社やプロジェクトを反映するファイル名プレフィックスを使用して、同じフォルダに新しいファイルを作成します。たとえば、開発者のプレフィックスがXYZ の場合、XYZ__styles.xml という名前の新しいファイルで sf__styles.xml を上書きできます。

次の文字列を含むファイル名

Mobile SDK スタイルで参照される色sf__colors.xml

Mobile SDK スタイルで参照されるサイズsf__dimens.xml

Mobile SDKスタイルで参照される文字列。エラーメッセージを上書きできます。

sf__strings.xml

Mobile SDK で使用されるビジュアルスタイルsf__styles.xml

アプリケーション定義の文字列strings.xml

strings.xml の値を上書きできます。ただし、create_native スクリプトを使用してアプリケーションを作成した場合、strings.xml の文字列はすでに適切な値を反映しています。

その他のリソースその他の 2 つのフォルダには、Mobile SDK リソースが含まれています。• res/menu は、内部的に使用されるメニューを定義します。アプリケーションで新しいメニューを定義す

る場合、新しいファイルのこの場所にリソースとして追加します。• res/xml には、編集する必要のあるファイル servers.xml が含まれています。このファイルでは、デ

フォルトの本番サーバおよび Sandbox サーバを組織のログインサーバに変更する必要があります。このフォルダにあるその他のファイルは内部で使用されます。authenticator.xml ファイルはアカウント認証リ

123

リソースの処理ネイティブ Android の開発

ソースを設定し、config.xml ファイルはハイブリッドアプリケーションの PhoneGap プラグインを定義します。

関連トピック:

Android リソース

REST API の使用Salesforce 組織からデータをクエリ、説明、作成、更新するために、ネイティブアプリケーションは Salesforce

REST API をコールします。Salesforce REST API は、SOQL文字列を優先しますが、JSON または XML 形式のデータを受け入れて返すこともできます。REST API についての詳細は、『Force.com REST API 開発者ガイド』を参照してください。関連する Salesforce 開発ドキュメントへのリンクは、Force.com 開発者向けドキュメントの Web サイトにあります。Android ネイティブアプリケーションにより、最小限のコーディングで REST コールを介して Salesforce データにアクセスできます。com.salesforce.androidsdk.rest パッケージのクラスは、通信チャネルを初期化して、低レベルの HTTP プラミングをカプセル化します。これらのクラスはすべてMobile SDKによって実装されていて、次のものがあります。• ClientManager — RestClient インスタンスのファクトリとして機能します。また、アカウントログインや

Salesforce サーバとのハンドシェイクも処理します。• RestClient — REST API 要求を Salesforce サーバに送信するためのプロトコルを処理します。

RestClientのインスタンスを直接作成しないでください。代わりに、ClientManager.getRestClient()

メソッドをコールします。• RestRequest — アプリケーションから提供されるデータに基づいて REST API 要求を書式設定します。ま

た、自身のインスタンスのファクトリとしても機能します。RestRequestのインスタンスを直接作成しないでください。代わりに、適切な RestRequestの静的 getter

関数 (RestRequest.getRequestForCreate() など) をコールします。• RestResponse — 要求された書式で応答コンテンツを書式設定して、書式設定した応答をアプリケーショ

ンに返し、コンテンツストリームを終了します。RestRequest クラスは、RestResponse のインスタンスを作成し、RestClient.AsyncRequestCallback インターフェースの実装を介してアプリケーションに返します。

次に、UI スレッドで REST クラスを使用する場合の基本手順を示します。1. ClientManager のインスタンスを作成します。

a. SalesforceSDKManager.getInstance().getAccountType()メソッドを使用して、ClientManager

コンストラクタの第 2 引数として渡す値を取得します。

b. ClientManager コンストラクタの LoginOptions パラメータの場合、SalesforceSDKManager.GetInstance().getLoginOptions() をコールします。

2. ClientManager.RestClientCallback インターフェースを実装します。

124

REST API の使用ネイティブ Android の開発

3. ClientManager.getRestClient() をコールして RestClient インスタンスを取得し、RestClientCallback 実装のインスタンスに渡します。native/SampleApps/RestExplorer サンプルアプリケーションの次のコードは、RestClientCallbackをインラインで実装およびインスタンス化しています。String accountType =

SalesforceSDKManager.getInstance().getAccountType();

LoginOptions loginOptions =SalesforceSDKManager.getInstance().getLoginOptions();

// Get a rest clientnew ClientManager(this, accountType, loginOptions,

SalesforceSDKManager.getInstance().shouldLogoutWhenTokenRevoked()).getRestClient(this, new RestClientCallback() {

@Overridepublic voidauthenticatedRestClient(RestClient client) {

if (client == null) {SalesforceSDKManager.getInstance().

logout(ExplorerActivity.this);return;

}// Cache the returned clientExplorerActivity.this.client = client;

}}

);

4. 静的 RestRequest() getter メソッドをコールして、ニーズに合った RestRequest オブジェクトを取得します。たとえば、Salesforce オブジェクトの説明を取得する場合は次のようになります。request = RestRequest.getRequestForDescribe(apiVersion, objectType);

5. 前のステップで取得した RestRequest オブジェクトを RestClient.sendAsync() またはRestClient.sendSync() に渡します。UI スレッドの場合、sendAsync() をコールします。a. ClientManager.AsyncRequestCallback インターフェースを実装します。b. 実装のインスタンスを sendAsync() メソッドに渡します。c. ASyncRequestCallback.onSuccess() メソッドを介して、書式設定された応答を取得します。

次のコードは、AsyncRequestCallback をインラインで実装およびインスタンス化しています。private void sendFromUIThread(RestRequest restRequest) {client.sendAsync(restRequest, new AsyncRequestCallback() {private long start = System.nanoTime();@Overridepublic void onSuccess(RestRequest request, RestResponse result) {try{// Do something with the result}catch (Exception e) {

125

REST API の使用ネイティブ Android の開発

printException(e);}EventsObservable.get().notifyEvent(EventType.RenditionComplete);}@Overridepublic void onError(Exception exception){printException(exception);EventsObservable.get().notifyEvent(EventType.RenditionComplete);}});

サービスから sendSync() メソッドをコールする場合、次の点を変更して同じ手順を実行します。1. RestClient インスタンスを取得するには、ClientManager.getRestClient() ではなく

ClientManager.peekRestClient() をコールします。

2. sendSync() メソッドの戻り値から、書式設定された REST 応答を取得します。

認証されていない REST 要求特定のケースでは、ユーザが認証される前に一部のアプリケーションで REST コールを実行する必要があります。その他のケースでは、アプリケーションで、Salesforce認証を必要としないSalesforce外のサービスにアクセスする必要があります。そのような要件を実装するには、認証トークンを必要としない特殊な RestClient

インスタンスを使用します。Android で認証されていない RestClientを取得するには、次のいずれかの ClientManagerファクトリメソッドを使用します。/*** Method to created an unauthenticated RestClient asynchronously* @param activityContext* @param restClientCallback*/public void getUnauthenticatedRestClient(Activity activityContext, RestClientCallbackrestClientCallback);/*** Method to create an unauthenticated RestClient.* @return*/public RestClient peekUnauthenticatedRestClient();

メモ: これらの RestClientオブジェクトのいずれかを介して送信された REST 要求では、フルパスの URL

が必要になります。Mobile SDK では、認証されていないエンドポイントの先頭にインスタンス URL は追加されません。

例:

RestClient unauthenticatedRestClient = clientManager.peekUnauthenticatedRestClient();RestRequest request = new RestRequest(RestMethod.GET,"https://api.spotify.com/v1/search?q=James%20Brown&type=artist", null);RestResponse response = unauthenticatedRestClient.sendSync(request);

126

認証されていない REST 要求ネイティブ Android の開発

ネイティブ Android アプリケーションのログインの延期forcedroid で Mobile SDK アプリケーションを作成する場合、多数の無料の標準機能を提供するテンプレートアプリケーションがプロジェクトのベースになります。たとえば、認証を実装する必要はなく、ログインとパスコードの処理はランチャーアクティビティに組み込まれています。この設計は大部分のアプリケーションで適切に機能し、この無償のコードにより、大幅に時間を節約できます。ただし、forcedroid アプリケーションを作成した後で、ランチャーアクティビティの実行後のある時点まで Salesforce 認証を延期する必要が生じる場合があります。認証の延期は、テンプレートアプリケーションの組み込み機能を維持したまま簡単に実装できます。次に、ガイドラインと注意事項を示します。• ランチャーアクティビティ (テンプレートアプリケーションの MainActivity) を、次のどの Mobile SDK ア

クティビティも拡張しないアクティビティに置き換えます。– SalesforceActivity

– SalesforceListActivity

– SalesforceExpandableListActivity

このルールは、Salesforceで認証する前に実行される他のすべてのアクティビティにも同様に適用されます。• peekRestClient()または getRestClient() ClientManagerメソッドは、ランチャーアクティビティ

や他の認証前のアクティビティからコールしないでください。• TemplateApp クラスの initNative() コールを変更しないでください。これは、認証後に起動するアク

ティビティクラス (テンプレートアプリケーションの MainActivity) を指し示している必要があります。• Salesforce で認証する準備が整ったら、MainActivity クラスを起動します。次の例は、Salesforce認証の前に非Salesforceアクティビティを置き換える方法を示します。もちろん、前述のガイドラインと注意事項に従って、その他の認証前のアクティビティでこの例を拡張することも可能です。1. アプリケーションの認証前のランディングページの XML レイアウトを作成します。たとえば、次のレイア

ウトファイル launcher.xml には、ログインフローをトリガするボタンのみがあります。

メモ: 次の例では、次のように res/strings.xml ファイルで定義される文字列リソース@string/login を使用します。<string name="login">Login</string>

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="@android:color/white"android:id="@+id/root">

<Button android:id="@+id/login_button"android:layout_width="80dp"android:layout_height="60dp"android:text="@string/login"android:textColor="@android:color/black"android:textStyle="bold"

127

ネイティブ Android アプリケーションのログインの延期ネイティブ Android の開発

android:gravity="center"android:layout_gravity="center"android:textSize="18sp"android:onClick="onLoginClicked" />

</LinearLayout>

2. ランディング画面アクティビティを作成します。たとえば、ここでは LauncherActivity という名前のランディング画面アクティビティを作成します。この画面は、launcher.xml で定義される XML レイアウトを拡張します。このクラスで Salesforce アクティビティを拡張したり、peekRestClient() またはgetRestClient()をコールしたりしないでください (これらのコールで認証フローがトリガされるため)。ユーザがログインボタンをタップすると、onLoginClicked() ボタンハンドラによって MainActivity

が起動され、ログインが行われます。package com.salesforce.samples.smartsyncexplorer.ui;

import com.salesforce.samples.smartsyncexplorer.R;

import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;

public class LauncherActivity extends Activity {@Overridepublic void onCreate(Bundle savedInstance) {

super.onCreate(savedInstance);setContentView(R.layout.launcher);

}

/*** Callback received when the 'Delete' button is clicked.** @param v View that was clicked.

*/public void onLoginClicked(View v) {

/** TODO: Add logic here to determine if we are already* logged in, and skip this screen by calling* 'finish()', if that is the case.*/final Intent mainIntent =

new Intent(this, MainActivity.class);mainIntent.addCategory(Intent.CATEGORY_DEFAULT);startActivity(mainIntent);finish();

}}

3. AndroidManifest.xml を変更し、アプリケーションの初回起動時に起動されるアクティビティとしてLauncherActivity を指定します。<!-- Launcher screen --><activity android:name=

128

ネイティブ Android アプリケーションのログインの延期ネイティブ Android の開発

"com.salesforce.samples.smartsyncexplorer.ui.LauncherActivity"android:label="@string/app_name"android:theme="@style/SalesforceSDK.ActionBarTheme"><intent-filter>

<action android:name="android.intent.action.MAIN" /><category

android:name="android.intent.category.LAUNCHER" /></intent-filter>

</activity>

<!-- Main screen --><activity android:name=

"com.salesforce.samples.smartsyncexplorer.ui.MainActivity"android:label="@string/app_name"android:theme="@style/SalesforceSDK.ActionBarTheme"><intent-filter>

<category android:name="android.intent.category.DEFAULT" />

</intent-filter></activity>

アプリケーションを起動すると、LauncherActivity 画面が表示されます。ログインボタンをクリックすると、Salesforce 認証フローが開始します。認証が完了すると、アプリケーションによって MainActivity が起動します。

Android テンプレートアプリケーション: 詳細TemplateApp サンプルプロジェクトは、基本的なネイティブ Android アプリケーションの作成に必要なすべてを実装します。これは「ベアボーン」サンプルであるため、Mobile SDK の create_native ant スクリプトで新しいネイティブ Android プロジェクトを設定するために使用するテンプレートとしても機能します。このアプリケーションを学習すれば、Mobile SDK for Android で作成されたネイティブアプリケーションを迅速に理解できます。TemplateApp プロジェクトでは、TemplateApp と MainActivity の 2 つのクラスが定義されています。• TemplateApp クラスは、Application を拡張し、その onCreate() 上書きで

SalesforceSDKManager.initNative() をコールします。• MainActivity クラスは、SalesforceActivity クラスをサブクラス化します。これらの 2 つのクラスがあれば、ログイン画面とホーム画面を表示するモバイルアプリケーションを作成できます。約 200 行のコードしか含まれていませんが、TemplateApp は単なる「Hello World」の例ではありません。このメインアクティビティでは、REST 要求を介して Salesforce データを取得し、その結果をモバイルページに表示します。Android オペレーティングシステム、デバイス、セキュリティの制限で許可されている範囲でアクティビティの追加や他のコンポーネントのコールなどを行って TemplateApp を拡張できます。

TemplateApp クラスすべてのネイティブ Android アプリケーションで android.app.Application のインスタンスが必要です。TemplateApp クラスは、次の 2 つの主要なタスクを実行します。

129

Android テンプレートアプリケーション: 詳細ネイティブ Android の開発

• initNative() をコールしてアプリケーションを初期化する• KeyInterface のアプリケーションの実装を渡す次に、クラス全体を示します。package com.salesforce.samples.templateapp;

import android.app.Application;

import com.salesforce.androidsdk.app.SalesforceSDKManager;

/*** Application class for our application.*/public class TemplateApp extends Application {

@Overridepublic void onCreate() {super.onCreate();SalesforceSDKManager.initNative(getApplicationContext(),new KeyImpl(), MainActivity.class);

}}

大部分のネイティブ Android アプリケーションは同じようなコードを使用できます。このわずかな作業で、アプリケーションはパスコードおよびログイン/ログアウトメカニズムを自由に実装でき、その他のいくつかの利点も得られます。「SalesforceActivity クラス、SalesforceListActivity クラス、および SalesforceExpandableListActivity クラス」を参照してください。

MainActivity クラスMobile SDK アプリケーションでは、メインアクティビティはユーザのログイン直後に始まります。メインアクティビティが実行されると、他のアクティビティを起動できるようになり、次にサブアクティビティを起動できるようになります。メインアクティビティを終了することで、アプリケーションが終了します。他のすべてのアクティビティは、メインアクティビティ内で連鎖的に終了します。テンプレートアプリケーションの MainActivity クラスは、Mobile SDK の抽象アクティビティクラスcom.salesforce.androidsdk.ui.sfnative.SalesforceActivity を拡張します。このスーパークラスで、必須のパスコードおよびログインプロトコルを自由に実装できます。代わりに別の基本アクティビティクラスを使用する場合、これらのプロトコルを自分で実装する必要があります。MainActivityは、アプリケーションの UI を初期化してその UI ボタンを実装します。MainActivity UI には、ユーザの Salesforce 取引先責任者または取引先を表示できるリストビューも含まれます。ユーザがこれらのいずれかのボタンをクリックすると、MainActivity オブジェクトが数個の基本クエリを実行して、ビューを作成します。たとえば、Salesforce からユーザの取引先責任者を取得する場合、onFetchContactsClick() メッセージハンドラが次のような単純な SOQL クエリを送信します。public void onFetchContactsClick(View v) throws UnsupportedEncodingException {

sendRequest("SELECT Name FROM Contact");}

130

Android テンプレートアプリケーション: 詳細ネイティブ Android の開発

内部的には、private sendRequest() メソッドが RestRequest クラスと指定の SOQL 文字列を使用して次のようにサーバ要求を生成します。private void sendRequest(String soql) throws UnsupportedEncodingException{

RestRequest restRequest =RestRequest.getRequestForQuery(

getString(R.string.api_version), soql);client.sendAsync(restRequest, new AsyncRequestCallback(){

@Overridepublic void onSuccess(RestRequest request,

RestResponse result) {try {

listAdapter.clear();JSONArray records =

result.asJSONObject().getJSONArray("records");for (int i = 0; i < records.length(); i++) {

listAdapter.add(records.getJSONObject(i).getString("Name"));

}} catch (Exception e) {

onError(e);}

}@Overridepublic void onError(Exception exception){

Toast.makeText(MainActivity.this,MainActivity.this.getString(

SalesforceSDKManager.getInstance().getSalesforceR().stringGenericError(),

exception.toString()),Toast.LENGTH_LONG).show();

}});

}

このメソッドは、com.salesforce.androidsdk.rest.RestClientクラスのインスタンス client を使用して SOQL クエリを処理します。RestClient クラスは、RestRequest と RestResponse の 2 つのヘルパークラスを使用して、クエリの送信とその結果の処理を行います。sendRequest() メソッドは、RestClient.sendAsync() をコールして SOQL クエリを非同期に処理します。sendRequest() メソッドは、sendAsync()コールに対応するために API バージョンと SOQL クエリ文字列を渡して com.salesforce.androidsdk.rest.RestRequestのインスタンスを作成します。生成されたオブジェクトは、sendAsync() の第 1 引数になります。第 2 引数は、コールバックオブジェクトです。sendAsync()

はクエリの実行の完了時に、このコールバックオブジェクトに結果を送信します。クエリに成功した場合、コールバックオブジェクトはクエリ結果を使用して UI リストのコントロールを設定します。クエリに失敗した場合、コールバックオブジェクトはトーストポップアップでエラーメッセージを表示します。

131

Android テンプレートアプリケーション: 詳細ネイティブ Android の開発

Java での匿名クラスの使用RestClient.sendAsync() へのコールで、コードは新しい AsyncRequestCallback オブジェクトを第 2 引数としてインスタンス化します。ただし、AsyncRequestCallbackconstructorの後に、いくつかのメソッド (onSuccess()や onError()) より優先されるコードブロックが続きます。このコードに不自然な点がある場合、よく状況を確認してください。ASyncRequestCallback は、インターフェースとして定義されるため、実装はありません。これをインスタンス化するために、コードで 2 つの ASyncRequestCallbackメソッドをインラインで実装して、匿名クラスオブジェクトを作成します。この手法により、別のオブジェクトからコールされない独自の sendAsync() 実装を TemplateApp に提供でき、一連の特殊なクラス名で API が見づらくなることもありません。

TemplateApp マニフェストTemplateApp プロジェクトの AndroidManifest.xml ファイルを見ると、Mobile SDK ネイティブ Android アプリケーションに必要なコンポーネントがわかります。必要なコンポーネントは、「.MainActivity」という名前のアクティビティのみです。このコンポーネントは、ログイン後に最初に呼び出されるアクティビティを表しています。この名前のクラスはプロジェクトで定義されます。次に AndroidManifest.xml の例を示します。

説明タイプ名前

ログイン後にコールされる最初のアクティビ

アクティビティ

MainActivity

ティ。名前とクラスはプロジェクトで定義されます。

forcedroid によって作成されたアプリケーションは、TemplateApp プロジェクトに基づいているため、MainActivity コンポーネントはすでにそのマニフェストに含まれています。他の Android アプリケーションと同様に、Android Studio でマニフェストを編集して他のコンポーネント (カスタムアクティビティまたはサービスなど) を追加できます。

チュートリアル: ネイティブ Android Warehouse アプリケーションの作成

モバイル在庫管理アプリケーションを構築することで、ネイティブ Android SDK の知識を応用します。このチュートリアルでは、2 つのアクティビティを定義する簡単な主従関係アーキテクチャについて説明します。また、Mobile SDK アプリケーションの設定、REST API ラッパークラスの使用、および Android SDK のインテグレーションについても説明します。

前提条件このチュートリアルでは、次のツールおよびパッケージが必要になります。

132

チュートリアル: ネイティブ Android Warehouse アプリケーションの作成

ネイティブ Android の開発

• このチュートリアルでは、基本的な在庫データベースを含む Warehouse アプリケーションを使用します。このアプリケーションを Developer Edition 組織にインストールする必要があります。既存の DE 組織にインストールする場合、作成した既存の Warehouse コンポーネントをすべて削除してからインストールしてください。1. インストール URL リンク http://goo.gl/1FYg90 をクリックします。2. ログインしている場合は、DE 組織のユーザ名とパスワードを入力します。3. 組織に適した表示レベルを選択します。4. [インストール] をクリックします。5. [完了] をクリックします。6. インストールが完了したら、右上のアプリケーションピッカーから [Warehouse (倉庫)] アプリケーショ

ンを選択できます。

7. データを作成するには、[Data (データ)] タブをクリックします。8. [Create Data (データを作成)] ボタンをクリックします。

• 次の最新バージョンをインストールします。– Java JDK 7 以降 — www.oracle.com/downloads。– Node Package Manager (npm) — SalesforceMobileSDK-Android リポジトリへの直接アクセスを含む、すべての

Android 開発シナリオでインストールする必要があります。– Android Studio 2 以降 — developer.android.com/sdk。– Android SDK および Android SDK Tools — Android Studio 内からインストールします。

1. Android Studio メニューで、[ツール] > [Android] > [SDK Manager] をクリックします。2. [SDK Platforms] タブをクリックします。3. 少なくとも次の必須 SDK レベルとすべての中間レベルをインストールします。

• 最小限の API: Android KitKat (API 19)

• 対象の API: Android Marshmallow (API 23)

133

前提条件ネイティブ Android の開発

4. [SDK Tools] タブをクリックします。5. 最新バージョンの Android SDK Tools をインストールします。

– Android 仮想デバイス (AVD) — Android Studio 内からインストールします。1. Android Studio メニューで、[ツール] > [Android] > [AVD マネージャ] をクリックします。2. [仮想デバイスを作成...] をクリックします。3. Android KitKat (API 19)以上を対象とする AVD を少なくとも 1 つインストールします。Android Studioで AVD

を設定する方法については、developer.android.com/guide/developing/devices/managing-avds.htmlの手順を参照してください。

• npm を使用して Salesforce Mobile SDK をインストールします。1. Node.js および npm がすでに正常にインストールされている場合は、ステップ 4 に進みます。2. Node.js をシステムにインストールします。Node.js インストーラにより、npm が自動的にインストールさ

れます。i. www.nodejs.org/download から Node.js をダウンロードします。ii. ダウンロードしたインストーラを実行して Node.js および npm をインストールします。インストール

の許可を求めるプロンプトをすべて承諾します。

3. ターミナルウィンドウで、「npm」と入力して Return キーを押し、インストールが成功していることを確認します。使用状況情報のページが表示されない場合、ステップ 2 に戻り、何が欠落しているのかを調べます。

4. ターミナルウィンドウで、「sudo npm install forcedroid -g」と入力します。このコマンドは、forcedroid パッケージを使用してMobile SDKをグローバルにインストールします。-gオプションでは、npm installを任意のディレクトリから実行できます。npm ユーティリティによりパッケージが /usr/local/lib/node_modules にインストールされ、/usr/local/bin のバイナリモジュールにリンクされます。大部分のユーザは /usr/local の「参照・更新」権限がないため、sudo

オプションが必要になります。

ネイティブ Android アプリケーションを作成するこのチュートリアルでは、Salesforce Mobile SDK の使用を開始する方法 (SDK のインストール方法や DE 組織を使用したネイティブプロジェクトテンプレートのツアーを含む) を学習します。後続のチュートリアルでは、テンプレートアプリケーションを変更して、Warehouse スキーマと連携させる方法について説明します。

ステップ 1: 接続アプリケーションを作成する接続アプリケーションは、モバイルアプリケーションが Force.com とセキュアに通信することを承認します。これは、Salesforce サービスと Force.com API にアクセスするために必要です。接続アプリケーションは、接続アプリケーションが定義されている組織だけでなく、有効なSalesforce組織であればどの組織へのアクセスも許可します。

134

ネイティブ Android アプリケーションを作成するネイティブ Android の開発

1. Developer Edition 組織で、[設定] から、[クイック検索] ボックスに「アプリケーション」と入力し、[アプリケーション] を選択します。

2. [接続アプリケーション] で、[新規] をクリックして、[新規接続アプリケーション] ページを表示します。3. [基本情報] で、フォームに次のように入力します。

• 接続アプリケーション名: My Native Android App (私のネイティブ Android アプリケーション)

• API 参照名: 推奨値を受け入れます。• 取引先責任者メール: メールアドレスを入力します。

4. OAuth 設定で、[OAuth 設定の有効化] チェックボックスをオンにします。5. [コールバック URL] を mysampleapp://auth/success に設定します。6. [利用可能な OAuth 範囲] で、[データへのアクセスと管理] (api) および [ユーザに代わっていつでも要求を実

行] (refresh_token) をオンにします。7. [追加] をクリックして、[保存] をクリックします。

重要: 接続アプリケーションについて、次の重要事項を考慮してください。• コールバック URL とコンシューマ鍵をコピーします。これらの値はネイティブアプリケーションの設

定に使用します。• Mobile SDK アプリケーションではコンシューマの秘密は使用しないため、この値は無視できます。• 接続アプリケーションの変更が有効になるまで数分かかります。

ステップ 2: ネイティブ Android プロジェクトを作成する新しい Mobile SDK プロジェクトを作成するには、ターミナルウィンドウで forcedroid ユーティリティをもう一度使用します。1. プロジェクトを作成するディレクトリに変更します。2. Android プロジェクトを作成するには、「forcedroid create」と入力します。

設定値ごとに、forcedroid ユーティリティによってプロンプトが表示されます。

3. アプリケーション種別に、「native」と入力します。4. アプリケーション名に、Warehouse と入力します。5. ターゲットディレクトリに、「tutorial/AndroidNative」と入力します。このディレクトリは、空の状

態で存在している必要があります。6. パッケージ名に、「com.samples.warehouse」と入力します。7. SmartStore を使用するかどうか確認を求められたら、[戻る] キーを押してデフォルトを受け入れます。

ステップ 3: 新しい Android アプリケーションを実行するAndroid アプリケーションが正常に作成されたため、このアプリケーションをビルドして実行し、設定を検証します。

135

ネイティブ Android アプリケーションを作成するネイティブ Android の開発

メモ: 問題が発生したら、まず Android SDK マネージャをチェックして、最新の Android SDK、ビルドツール、および開発ツールを取得していることを確認します。Android SDK マネージャは、Android Studioの [Tools

(ツール)] > [Android] > [SDK Manager (SDK マネージャ)] にあります。欠落しているもののすべてをインストールしたら、Android SDK マネージャを終了して再起動し、確実に最新の状態にします。

Android Studio でのアプリケーションのインポートおよび作成forcedroid スクリプトにより、Android Studio エディタで新しいアプリケーションを実行する手順が出力されます。1. Android Studio を起動し、ようこそ画面から [Import Project (Eclipse ADT, Gradle, etc.) (プロジェクトをインポー

ト (Eclipse ADT、Gradle など))] を選択します。2. tutorial/AndroidNative フォルダを選択し、[OK] をクリックします。3. 「Unregistered VCS roots detected」(未登録の VCS ルートが検出されました) というメッセージが表示されたら、

[Add roots (ルートを追加)] をクリックします。Android Studioによってワークスペースが自動的に作成されます。このプロセスに数分かかることがあります。ステータスバーにエラーが表示されていなければ、アプリケーションを実行できます。1. ターゲットドロップダウンメニューから、[Warehouse (倉庫)] を選択します。2. [Run (実行)] をクリックするか、SHIFT+F10 キーを押します。Android Studioによってエミュレータまたは接続されている Android デバイスにアプリケーションが起動します。

ステップ 4: Android アプリケーションの仕組みを探索するネイティブ Android アプリケーションは、簡単な Model View Controller (MVC) アーキテクチャを使用します。• モデルは、Warehouse データベーススキーマです。• ビューは、プロジェクトで定義されたアクティビティから取得します。• コントローラの機能は、Android SDK クラス、Salesforce Mobile SDK、およびアプリケーションを相互に連携さ

せることです。ビュー内で、完成したチュートリアルアプリケーションは主従関係にある 2 つの Android アクティビティを定義します。MainActivity は、Merchandise カスタムオブジェクトのレコードを一覧表示します。MainActivity の項目をクリックしてアクセスする DetailActivity では、選択したレコードの項目を表示および編集できます。

MainActivity クラスアプリケーションが起動すると、WarehouseApp クラスが初めに実行フローを制御します。ログインプロセスが完了したら、WarehouseAppインスタンスは、SalesforceSDKManagerシングルトンを介して制御をメインアクティビティクラスに渡します。新しいアプリケーションの基盤として機能するテンプレートアプリケーションや、完成したチュートリアルでは、メインアクティビティクラスに MainActivity という名前が付けられています。このクラスは、すべてのアクティビティの Mobile SDK 基本クラスである SalesforceActivity をサブクラス化します。ただし、カスタマイズするまでは、アプリケーションに他のアクティビティやタッチイベントハンドラは含まれていません。Salesforce にログインし、Salesforce Mobile SDK REST API を使用して要求を発行し、メインアクティ

136

ネイティブ Android アプリケーションを作成するネイティブ Android の開発

ビティで応答を表示するだけです。このチュートリアルでは、テンプレートアプリケーションのコントロールを置き換えて、SOQL REST 要求の目的を再設定し、Warehouse スキーマの Merchandise カスタムオブジェクトと連携するようにします。

DetailActivity クラスまた、DetailActivity クラスも SalesforceActivity をサブクラス化しますが、さらに興味深いカスタマイズを示します。DetailActivity は、標準の Android SDK クラスおよび XML テンプレートを使用して、テキスト編集を実装します。また、Mobile SDK の RestClientおよび RestRequestクラスを使用して、Salesforce

のデータベースオブジェクトを更新する方法も示します。

RestClient クラスと RestRequest クラスMobile SDK アプリケーションは、REST API を介して Salesforce データを操作します。ただし、独自の REST 要求を作成したり、HTTP レベルで直接作業したりする必要はありません。RestRequest クラスの便利な静的メソッドを使用することで、最小限のコーディングで SOQL クエリの処理、SOSL 検索、および CRUD 操作を行うことができます。便利な各 RestRequestメソッドは、書式設定された REST 要求をラップする RestRequestオブジェクトを返します。要求をサーバに送信するには、RestClient インスタンスの sendAsync() または sendSync() メソッドにRestRequest オブジェクトを渡します。RestClient オブジェクトは作成しません。アクティビティでSaleforceActivity などの Mobile SDK アクティビティクラスを継承すると、Mobile SDK は RestClient のインスタンスを onResume() メソッドに渡します。または、ClientManager.getRestClient() をコールすることもできます。アプリケーションは、RestClient オブジェクトが代理で REST 要求を送信できるようにbootconfig.xml ファイルの接続アプリケーション情報を使用します。

リスト画面をカスタマイズするこのチュートリアルでは、メインアクティビティとそのレイアウトを修正し、Warehouse スキーマ固有のアプリケーションを作成します。また、Merchandise カスタムオブジェクトから必要なすべての情報を取得できるように、既存の SOQL クエリを適合させます。

ステップ 1: 既存のコントロールを削除するテンプレートコードで提供されるメインアクティビティ画面は、目的に合っていません。コード用の領域を確保しましょう。1. Android Studio のプロジェクトウィンドウから、res/layout/main.xml ファイルを開きます。ビューをテ

キスト形式モードに設定してください。この XML ファイルには <LinearLayout>ルートノードがあり、このルートノードには、<include> ノード、ネストされた <LinearLayout> ノード、および <ListView>

ノードの 3 つの子ノードが含まれています。2. 3 つの <Button>ノードがある、ネストされた <LinearLayout>ノードを削除します。編集したファイル

は次のようになります。<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

137

リスト画面をカスタマイズするネイティブ Android の開発

android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#454545"android:id="@+id/root">

<include layout="@layout/header" />

<ListViewandroid:id="@+id/contacts_list"android:layout_width="match_parent"android:layout_height="match_parent" />

</LinearLayout>

3. ファイルを保存し、src/com.samples.warehouse/MainActivity.java ファイルを開きます。4. onClearClick()、onFetchAccountsClick()、および onFetchContactsClick() メソッドを削除し

ます。sendRequest() メソッドがローカルで使用されていないことがコンパイラで警告されても問題ありません。そのメソッドへのコールをすべて削除しましたが、次のステップで修正します。

ステップ 2: SOQL クエリを更新するsendRequest() メソッドには、SOQL クエリを REST 要求として送信するためのコードがあります。このコードの一部は再利用できますが、残りの部分は新しいアプリケーションに合わせてカスタマイズします。1. sendRequest() を fetchDataForList() に名前変更します。置換

private void sendRequest(String soql) throws UnsupportedEncodingException

置換後private void fetchDataForList()

throw 宣言が削除されています。引き続きローカルで例外処理を行うために、メソッド本文内でこの宣言を復帰させます。fetchDataForList() コール元に例外をスローするのではなく、RestRequest.getRequestForQuery()へのコールを囲むように try...catchブロックを追加します。

2. Merchandise__c カスタムオブジェクトから最大 10 個のレコードを返すハードコード化された SOQL クエリを追加します。private void fetchDataForList() {

String soql = "SELECT Name, Id, Price__c, Quantity__cFROM Merchandise__c LIMIT 10";

3. RestRequest.getRequestForQuery() へのコールを try...catch ブロックで囲みます。置換前のステートメントは、次のとおりです。RestRequest restRequest = RestRequest.getRequestForQuery(getString(R.string.api_version),soql);

置換後RestRequest restRequest = null;try {

138

リスト画面をカスタマイズするネイティブ Android の開発

restRequest =RestRequest.getRequestForQuery(getString(R.string.api_version), soql);

} catch (UnsupportedEncodingException e) {showError(MainActivity.this, e);return;

}

次に、完成バージョン (元は sendRequest() メソッド) を示します。private void fetchDataForList() {

String soql = "SELECT Name, Id, Price__c, Quantity__c FROMMerchandise__c LIMIT 10";

RestRequest restRequest = null;try {

restRequest =RestRequest.getRequestForQuery(

getString(R.string.api_version), soql);} catch (UnsupportedEncodingException e){

showError(MainActivity.this, e);return;

}

client.sendAsync(restRequest, new AsyncRequestCallback() {@Overridepublic void onSuccess(RestRequest request,

RestResponse result) {try {

listAdapter.clear();JSONArray records =

result.asJSONObject().getJSONArray("records");for (int i = 0; i < records.length(); i++) {

listAdapter.add(records.getJSONObject(i).getString("Name"));

}} catch (Exception e) {

onError(e);}

}

@Overridepublic void onError(Exception exception) {

Toast.makeText(MainActivity.this,MainActivity.this.getString(

SalesforceSDKManager.getInstance().getSalesforceR().stringGenericError(),exception.toString()),

Toast.LENGTH_LONG).show();}

});}

画面が読み込まれて認証が完了したら、fetchDataForList() をコールします。

139

リスト画面をカスタマイズするネイティブ Android の開発

4. onResume(RestClient client) メソッドで、メソッド本文の最後に次の行を追加します。@Overridepublic void onResume(RestClient client) {

// Keeping reference to rest clientthis.client = client;

// Show everythingfindViewById(R.id.root).setVisibility(View.VISIBLE);// Fetch data for listfetchDataForList();

}

5. 最後に、特定のアクティビティコンテキストでエラーをレポートする showError() メソッドを実装します。ファイルの上部で、インポートのリストの最後に次の行を追加します。import android.content.Context;

6. MainActivity クラス定義の最後に、次のコードを追加します。public static void showError(Context context, Exception e) {

Toast toast = Toast.makeText(context,context.getString(

SalesforceSDKManager.getInstance().getSalesforceR().stringGenericError(),

e.toString()),Toast.LENGTH_LONG);

toast.show();}

7. MainActivity.java ファイルを保存します。

ステップ 3: アプリケーションを試すAndroid Studio でアプリケーションを構築して実行します。Android エミュレータが表示されたら、読み込みが完了するまで数分待機します。画面のロックを解除して、Salesforce ログイン画面が表示されるまでもうしばらく待機します。Salesforce に正常にログインできたら、[許可] をクリックして必要な権限をアプリケーションに付与します。この時点で Merchandise レコードをクリックしても何も起きません。次のチュートリアルでこれを修正します。

詳細画面を作成する前のステップで、メインアクティビティで最大 10 個の Merchandise レコードのリストを表示するようにテンプレートアプリケーションを変更しました。このステップでは、詳細アクティビティおよびレイアウトを作成して作業を終了します。次に、メインアクティビティと詳細アクティビティをリンクします。

ステップ 1: 詳細画面を作成するまず、res/layout/detail.xml という名前の XML ファイルを作成して詳細アクティビティのレイアウトを設計します。

140

詳細画面を作成するネイティブ Android の開発

1. Package Explorer で、res/layout を展開します。2. Ctrl キーを押しながら layout フォルダをクリックし、[New (新規)] > [Android XML File (Android XML ファイル)]

を選択します。3. [File (ファイル)] 項目で、detail.xml と入力します。4. [Root Element (ルート要素)] で、[LinearLayout] を選択します。5. [Finish (完了)] をクリックします。

新しいファイルで、詳細画面で使用されるレイアウトおよびリソースを定義します。まず、名前、価格、数量の項目および表示ラベルを追加します。

6. 新しいファイルのコンテンツを次の XML コードで置き換えます。<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/root"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#454545"android:orientation="vertical" >

<include layout="@layout/header" />

<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/name_label"android:width="100dp" />

<EditTextandroid:id="@+id/name_field"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="text" />

</LinearLayout>

<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/price_label"android:width="100dp" />

<EditText

141

詳細画面を作成するネイティブ Android の開発

android:id="@+id/price_field"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="numberDecimal" />

</LinearLayout>

<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" >

<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/quantity_label"android:width="100dp" />

<EditTextandroid:id="@+id/quantity_field"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="number" />

</LinearLayout>

</LinearLayout>

7. ファイルを保存します。8. レイアウトを終了するには、TextView要素で参照される 3 つの表示ラベル (name_label、price_label、

および quantity_label) の表示名を定義します。res/values/strings.xml にある <resources> ノードの終了直前に次のコードを追加します。<!-- Detail screen --><string name="name_label">Name</string><string name="price_label">Price</string><string name="quantity_label">Quantity</string>

9. ファイルを保存し、テキストビューで AndroidManifest.xmlファイルを開きます。テキストビューを取得できない場合、エディタ画面の下部にある [AndroidManifest.xml] タブをクリックします。

10. <application> セクションに次のコードを追加して、AndroidManifest.xml で新しいアクティビティを宣言します。<!-- Merchandise detail screen --><activity android:name="com.samples.warehouse.DetailActivity"

android:theme="@android:style/Theme.NoTitleBar.Fullscreen"></activity>

後で追加するボタンを除き、詳細画面のレイアウトおよび文字列リソースの設計は完了しました。画面の動作を実装するには、新しいアクティビティを定義します。

142

詳細画面を作成するネイティブ Android の開発

ステップ 2: DetailActivity クラスを作成するこのモジュールでは、com.samples.warehouseパッケージで DetailActivity.javaという名前の新しいクラスファイルを作成します。1. Package Explorer で、[WarehouseApp] > [src] > [com.samples.warehouse] ノードを展開します。2. Ctrl キーを押しながら com.samples.warehouse フォルダをクリックし、[New (新規)] > [Class (クラス)] を

選択します。3. [Name (名前)] 項目で、「DetailActivity」と入力します。4. [Superclass (スーパークラス)]項目で、com.salesforce.androidsdk.ui.sfnative.SalesforceActivity

を入力または参照します。5. [Finish (完了)] をクリックします。

コンパイラは、必要な onResume() メソッドのスタブ実装を提供します。Mobile SDK は、RestClient のインスタンスをこのメソッドに渡します。REST API 要求を作成するには、このインスタンスが必要であるため、インスタンスへの参照をキャッシュすることをお勧めします。

6. 新しいクラスの上部にあるメンバー変数のリストに次の宣言を追加します。private RestClient client;

7. onResume() メソッド本文で、次のコードを追加します。@Overridepublic void onResume(RestClient client) {

// Keeping reference to rest clientthis.client = client;

}

ステップ 3: DetailActivity クラスをカスタマイズするアクティビティの設定を完了するには、Merchandise 項目値の編集を処理するように DetailActivity クラスをカスタマイズします。1. DetailActivity.java の上部にあるインポートリストに次のインポートを追加します。

import android.widget.EditText;import android.os.Bundle;

2. クラス本文の上部で、3 つの入力項目に対応する非公開 EditText メンバーを追加します。private EditText nameField;private EditText priceField;private EditText quantityField;

3. Merchandise カスタムオブジェクトのレコード ID を格納する変数を追加します。後でメインアクティビティと詳細アクティビティをリンクするときに、この変数を入力するコードを追加します。private String merchandiseId;

143

詳細画面を作成するネイティブ Android の開発

4. 作成した detail.xml レイアウトを使用するようにビューを設定する onCreate() メソッドを追加します。このメソッドをクラス定義の最後の直前に配置します。@Overrideprotected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// Setup viewsetContentView(R.layout.detail);nameField = (EditText) findViewById(R.id.name_field);priceField = (EditText) findViewById(R.id.price_field);quantityField = (EditText)

findViewById(R.id.quantity_field);}

ステップ 4: 2 つのアクティビティをリンクする - 第 1 部: データクラスを作成する次に、MainActivityクラスと DetailActivityクラスを接続し、選択した Merchandise レコードの項目を共有できるようにする必要があります。ユーザが在庫リストの項目をクリックしたら、MainActivity は、レコードの項目を表示するために必要なデータと共に DetailActivity を起動する必要があります。現時点では、MainActivity.java のリストアダプタには Merchandise 項目の名前のみがあります。標準項目(id と name) およびカスタム項目 (quantity と price) の値をローカルに保存して、これらを詳細画面に送信できるようにしましょう。まず、Merchandise レコードを表す静的データクラスを定義します。1. Package Explorer で、[src] > [com.samples.warehouse] > [MainActivity.java] を開きます。2. MainActivity 定義の最後に、次のクラス定義を追加します。

/*** Simple class to represent a Merchandise record*/static class Merchandise {public final String name;public final String id;public final int quantity;public final double price;

public Merchandise(String name, String id, int quantity, double price) {this.name = name;this.id = id;this.quantity = quantity;this.price = price;}

public String toString() {return name;}}

144

詳細画面を作成するネイティブ Android の開発

3. このクラスを機能させるには、文字列ではなく Merchandise オブジェクトのリストを取得するようにメインアクティビティのリストアダプタを変更します。listAdapter 変数の宣言で、テンプレートの種類をString から Merchandise に変更します。private ArrayAdapter<Merchandise> listAdapter;

4. 新しい種類に合わせて、onResume() メソッドで listAdapter のインスタンス化を変更します。listAdapter = new ArrayAdapter<Merchandise>(this, android.R.layout.simple_list_item_1,

new ArrayList<Merchandise>());

次に、SOQL コールの応答を受信したときに listAdapter オブジェクトを入力するコードを変更します。

5. ファイルの上部にある既存のリストに次のインポートを追加します。import org.json.JSONObject;

6. 新しい Merchandise オブジェクトを使用するように fetchDataForList() の onSuccess() メソッドを変更します。public void onSuccess(RestRequest request, RestResponse result) {try {listAdapter.clear();JSONArray records = result.asJSONObject().getJSONArray("records");for (int i = 0; i < records.length(); i++) {JSONObject record = records.getJSONObject(i);Merchandise merchandise =new Merchandise(record.getString("Name"),record.getString("Id"), record.getInt("Quantity__c"),record.getDouble("Price__c"));listAdapter.add(merchandise);}} catch (Exception e) {onError(e);}}

ステップ 5: 2 つのアクティビティをリンクする - 第 2 部: リスト項目クリックハンドラを実装する次に、クリックイベントをキャッチして、これらのイベントの発生時に詳細画面を起動する必要があります。MainActivity をリストビュー項目のクリックのリスナーにします。1. エディタで MainActivity.java ファイルを開きます。2. 次のインポートを追加します。

import android.widget.AdapterView.OnItemClickListener;

3. クラス宣言を変更して、OnItemClickListener インターフェースを実装します。public class MainActivity extends SalesforceActivity implements OnItemClickListener {

145

詳細画面を作成するネイティブ Android の開発

4. このリストビューの非公開メンバーを追加します。private ListView listView;

5. super.onResume() コールの直前の onResume() メソッドに次の太字のコードを追加します。public void onResume() {

// Hide everything until we are logged infindViewById(R.id.root).setVisibility(View.INVISIBLE);

// Create list adapterlistAdapter = new ArrayAdapter<Merchandise>(

this, android.R.layout.simple_list_item_1, new ArrayList<Merchandise>());((ListView) findViewById(R.id.contacts_list)).setAdapter(listAdapter);

// Get a handle for the list viewlistView = (ListView) findViewById(R.id.contacts_list);listView.setOnItemClickListener(this);

super.onResume();}

リスト項目クリック用のリスナーを指定したので、リスト項目クリックハンドラを追加できます。

6. 次のインポートを追加します。import android.widget.AdapterView;import android.content.Intent;

7. Merchandise クラス定義の直前に、onItemClick() メソッドを追加します。public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

}

8. Merchandise オブジェクトの形式でリストアダプタから選択された項目を取得します。public void onItemClick(AdapterView<?> parent, View view, int position, long id) {Merchandise merchandise = listAdapter.getItem(position);

}

9. 商品の詳細を渡して、詳細アクティビティを開始する Android のインテントを作成します。public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

Merchandise merchandise = listAdapter.getItem(position);Intent intent = new Intent(this, DetailActivity.class);intent.putExtra("id", merchandise.id);intent.putExtra("name", merchandise.name);intent.putExtra("quantity", merchandise.quantity);intent.putExtra("price", merchandise.price);startActivity(intent);

}

インテントから商品の詳細を抽出できるように DetailActivity クラスを更新して、終了しましょう。

146

詳細画面を作成するネイティブ Android の開発

10. Package Explorer で、[src] > [com.samples.warehouse] > [DetailActivity.java] を開きます。11. onCreate() メソッドで、リスト画面の選択値を詳細アクティビティの対応するデータメンバーに割り当

てます。protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// Setup viewsetContentView(R.layout.detail);nameField = (EditText) findViewById(R.id.name_field);priceField = (EditText) findViewById(R.id.price_field);quantityField = (EditText)

findViewById(R.id.quantity_field);// Populate fields with data from intentBundle extras = getIntent().getExtras();merchandiseId = extras.getString("id");nameField.setText(extras.getString("name"));priceField.setText(extras.getDouble("price") + "");quantityField.setText(extras.getInt("quantity") + "");

}

ステップ 6: [更新] ボタンを実装するもう少しで作業は終了します。不足している UI は、ユーザの編集内容をサーバに書き込むためのボタンのみです。次の操作を行う必要があります。• ボタンをレイアウトに追加する• ボタンの表示ラベルを定義する• クリックハンドラを実装する• 編集内容をサーバに保存する機能を実装する1. detail.xml を再度開き、次の <Button> ノードを最も外側のレイアウトの最後のノードとして追加しま

す。<Button

android:id="@+id/update_button"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="onUpdateClick"android:text="@string/update_button" />

2. detail.xml ファイルを保存し、strings.xml を開きます。3. 次のボタンの表示ラベル文字列を文字列リストの最後に追加します。

<string name="update_button">Update</string>

4. strings.xml ファイルを保存し、DetailActivity.java を開きます。DetailActivityクラスで、[更新] ボタンの onClickイベントのハンドラを追加します。ハンドラの名前は、detail.xml に追加した <Button> ノードの android:onClick 値と一致している必要があります。

147

詳細画面を作成するネイティブ Android の開発

この場合、名前は onUpdateClickです。このメソッドは単に、Merchandise__c項目名をそれに対応する詳細画面の値と照合する対応付けを作成します。値が設定されると、saveData() メソッドをコールして、変更内容をサーバに書き込みます。

5. ハンドラをサポートするには、ファイルの上部にある既存のリストに次のインポートを追加します。import java.util.HashMap;import java.util.Map;import android.view.View;

6. 次のメソッドを DetailActivity クラス定義に追加します。public void onUpdateClick(View v) {Map<String, Object> fields = new HashMap<String, Object>();fields.put("Name", nameField.getText().toString());fields.put("Quantity__c", quantityField.getText().toString());fields.put("Price__c", priceField.getText().toString());saveData(merchandiseId, fields);}

saveData()が定義されていないことがコンパイラから通知されます。これを修正しましょう。saveData()

メソッドは、ユーザの値を使用して Merchandise__c オブジェクトを更新する REST API 更新要求を作成します。次に、RestClient.sendAsync()メソッドを使用して、非同期に要求をサーバに送信します。サーバ応答 (またはサーバエラー) を受信するコールバックメソッドは、sendAsync()コールでインラインで定義されます。

7. ファイルの上部にある既存のリストに次のインポートを追加します。import com.salesforce.androidsdk.rest.RestRequest;import com.salesforce.androidsdk.rest.RestResponse;

8. saveData() メソッドを DetailActivity クラス定義に実装します。private void saveData(String id, Map<String, Object> fields) {RestRequest restRequest;try {restRequest = RestRequest.getRequestForUpdate(getString(R.string.api_version),"Merchandise__c", id, fields);

} catch (Exception e) {// You might want to log the error or show it to the userreturn;}

client.sendAsync(restRequest, new RestClient.AsyncRequestCallback() {@Overridepublic void onSuccess(RestRequest request, RestResponse result) {try {DetailActivity.this.finish();} catch (Exception e) {// You might want to log the error// or show it to the user}}

148

詳細画面を作成するネイティブ Android の開発

@Overridepublic void onError(Exception e) {// You might want to log the error// or show it to the user}});}

これで完成です。アプリケーションを実行してテストする準備ができました。

ステップ 7: アプリケーションを試す1. アプリケーションを構築し、Android エミュレータで実行します。すべて適切に行った場合、Warehouse 画面

の Merchandise レコードをクリックしたときに詳細ページが表示されます。2. レコードの数量と価格を更新します。値を編集した後で詳細ビューの [更新] ボタンをクリックしてくださ

い。詳細ビューに戻ると、更新された値が表示されます。3. DE 組織にログインして、ブラウザ UI でレコードを表示し、更新された値を確認します。

Android サンプルアプリケーション

Salesforce Mobile SDK には、次のネイティブ Android サンプルアプリケーションがあります。• RestExplorer: Mobile SDKの OAuth および REST API 機能を示します。また、REST API アクションをタブレットから

調べる場合にも便利です。• SmartSyncExplorer: Android 上でのネイティブ SmartSync ライブラリの機能を示します。これは、

native/NativeSampleApps/SmartSyncExplorer の Mobile SDK for Android にあります。Mobile SDKの hybrid/HybridSampleApps/には、いくつかのハイブリッドアプリケーション用に Android ラッパーもあります。• AccountEditor: smartsync.js ライブラリを使用してオフラインデータを同期する方法について説明しま

す。• NoteSync: 非 REST API を使用して Salesforce のメモを取得する方法を示します。• SmartSyncExplorerHybrid: SmartSync プラグインを使用してオフラインデータを同期する方法について説明し

ます。

149

Android サンプルアプリケーションネイティブ Android の開発

第 9 章 HTML5 およびハイブリッド開発

HTML5 により、ターゲットデバイスにソフトウェアをインストールせずに、軽量モバイルインターフェースを作成できます。どのモバイルデバイス、タッチデバイス、

トピック:

• はじめに デスクトップデバイスからでも、このモバイルインターフェースにアクセスできま• HTML5 開発ツール す。HTML5 でカメラや GPS など高度なモバイル機能がサポートされるようになり、

これらの一般的なデバイス機能を Salesforce モバイルアプリケーションで簡単に使用できるようになりました。

• Visualforce を使用した HTML5 コンテンツの配信 次の方法で、Force.com プラットフォームを使用する HTML5 アプリケーションを作成

できます。• Salesforce データへのアクセス: コントローラと API • Visualforce を使用して、HTML コンテンツを配信する。

• JavaScript Remotingを使用して、Force.com からレコードを取得するためのApexコントローラを呼び出す。

• ハイブリッドアプリケーションのクイックスタート また、スタンドアロンのMobile SDKハイブリッドアプリケーションで HTML5 コードを

再設定し、App Store から配布することもできます。ハイブリッドに変換するには、• ハイブリッドアプリケーションの作成

サードパーティの Cordova コマンドラインを使用して Mobile SDK コンテナプロジェクトを作成してから、HTML5、JavaScript、および CSS ファイルをこのプロジェクトにインポートします。• モバイルデバイス

でのハイブリッドアプリケーションのデバッグ

• iOS 7 ハイブリッドアプリケーションでのステータスバーの制御

• ハイブリッドアプリケーションのJavaScript ファイル

• バージョン設定および JavaScript ライブラリの互換性

• ハイブリッドアプリケーションでのセッション管理

• ログインの延期• Android ハイブリッ

ドアプリケーションからの SmartStoreと SmartSync の削除

• 例: 適切な JavaScriptライブラリの提供

150

はじめに

Web 開発者には、Salesforce にアクセスする HTML5 アプリケーションを作成する準備が整えられています。HTML5

アプリケーションはブラウザで実行可能で、Salesforce Mobile SDKは必要ありません。開発者の作業は、Salesforce

API をコールして戻り値を取得し、それをロジックと UI につなげるだけです。モバイルブラウザで他のアプリケーションを実行する場合と同じ利点と課題がありますが、Salesforce とそのパートナーがモバイル Web 設計およびコーディングの合理化に役立つツールを提供しています。HTML5 アプリケーションをハイブリッドコンテナでスタンドアロンとして開発し、Apple® AppStore®または Android

マーケットプレイスで配布する場合は、Mobile SDK を使用してハイブリッドアプリケーションを作成する必要があります。

HTML5 および JavaScript の使用HTML5 コードおよび JavaScript コードを記述するために、Xcode や Microsoft® Visual Studio® などの専門的な開発環境は必要ありません。最新のブラウザには、HTML や JavaScript デバッガなどの高度な開発機能が含まれています。実際、アプリケーションをテキストエディタで作成し、ブラウザでテストすることができます。ただし、コーディング作業を最小限に抑える上で役立つ、業界の主要なライブラリに関しての十分な知識は必要です。モバイル開発の近年の成長により、新しい Web 技術ツールキットが急増しました。これらの JavaScript ライブラリの多くはオープンソースで、ライセンスは必要ありません。HTML5 開発用にSalesforceで提供されるほとんどのツールは、このようなサードパーティ技術で構築されています。

HTML5 の開発要件ブラウザベースの HTML5 Salesforce アプリケーションの作成を計画している場合は、Salesforce Mobile SDKは必要ありません。• Force.com 組織が必要です。• Apex および Visualforce に関する多少の知識が必要です。

メモ: このタイプの開発では、Visualforce を使用します。Database.com は使用できません。

マルチデバイス戦略モバイルデバイスは世界的に普及しているため、HTML5 モバイルアプリケーションはさまざまなプラットフォームやフォーム要素、デバイス機能に対応する必要があります。Visualforce でデバイスに依存しないモバイルアプリケーションを作成する開発者は、次の重要な設計上の検討事項に直面します。• アプリケーションでどのデバイスやフォーム要素をサポートするか?

• アプリケーションでデバイスの種類をどのように検出するか?

• 数種のデバイスを適切にサポートする Force.com アプリケーションをどのように設計するか?

151

はじめにHTML5 およびハイブリッド開発

どのデバイスやフォーム要素をサポートするか?この検討事項に対する答えは、特定の用途やエンドユーザの要望によって異なります。ただし、具体的にどのデバイス、プラットフォーム、フォーム要素をサポートする必要があるかを時間をかけて検討することは重要です。「あらゆるプラットフォーム、デバイス、フォーム要素をサポート」から、たとえば「デスクトップとiPhone のみサポート」までの広いサポート範囲でどの程度サポートするかによって、上記の残りの 2 つの検討事項への回答が大きく左右されます。お分かりのように、この決定を下す際には重要なトレードオフを考慮する必要があります。多くのフォーム要素をサポートすれば、当然アプリケーションの利用者層が増加します。しかし、アプリケーションの初期開発と長期的な管理の両面においては複雑性が増大するという犠牲を伴います。真のクロスデバイスアプリケーションの開発とは、どのフォーム要素やデバイス (デスクトップ、スマートフォン、タブレット) でも Web ページの表示 (およびパフォーマンス) を最適にするという単純な問題ではありません。特定のデバイスやフォーム要素ごとにユーザ操作性を再考してカスタマイズする必要に迫られます。スマートフォンやタブレット向けのアプリケーションでは、デスクトップ向けに最適化された既存の Web ページでサポートされる付加的な機能 (ファイルのアップロードや、多数の異なるクリック操作を要する使用事例のサポートなど) が必要なことはほとんどありません。反対に、スマートフォンやタブレット向けのアプリケーションでは、地理位置情報や写真撮影といった、デスクトップ環境では不可能な機能をサポートできます。LinkedIn や Flipboard のような優れた設計のアプリケーションでは、スマートフォン向けとタブレット向けでも機能が大きく異なります (たとえば、タブレット向けは水平ナビゲーションで、スマートフォン向けは片手操作の垂直スクロール)。アプリケーションでどのデバイスおよびフォーム要素をサポートするかを決定するときは、これらのすべての事項に加え、サポートに関連して必要な時間とコストも考慮します。どのデバイスをサポートするかを決定したら、特定のユーザがどのデバイスから Web アプリケーションにアクセスしているかを検出する必要があります。

クライアント側での検出クライアント側の検出アプローチでは、クライアントブラウザ上で実行されている JavaScript (または CSS メディアクエリ) を使用してデバイスの種類を判別します。具体的には、次の 2 つの方法でデバイスの種類を検出できます。• ユーザエージェントヘッダーによるクライアント側のデバイス検出 — このアプローチでは、JavaScript を使

用してユーザエージェント HTTP ヘッダーを解析し、この情報に基づいてデバイスの種類を判別します。もちろん、この判別を行う独自の JavaScript を記述することも可能ですが、既存の JavaScript を再利用することをお勧めします。インターネットをざっと検索しただけでも、ユーザエージェントヘッダーに基づいてデバイスの種類を検出できる再利用可能な JavaScript スニペットが多数見つかります。ただし、こうした検索では、このアプローチを使用した場合の危険性も知ることになります。使用される可能性のある全ユーザエージェントのリストは膨大なうえ現在も増え続けていることから、この方法は概して信頼性が低いものと考えられています。

• 画面サイズやデバイス機能によるクライアント側のデバイス検出 — JavaScript のユーザエージェント文字列を探るよりも適切な代替法は、デバイスの画面サイズや機能 (タッチ対応など) に基づいてデイバスの種類を判別することです。オープンソースの Contact Viewer HTML5 モバイルアプリケーションはこのアプローチの一例で、すべて Visualforce で構築されています。具体的には、MobileAppTemplate.page のページ上部に、デバイスの画面サイズに基づいてスマートフォンとタブレットを判別するシンプルな JavaScript スニペットが

152

マルチデバイス戦略HTML5 およびハイブリッド開発

記述されています。もう 1 つのオプションは、Device.js や Modernizr などのライブラリを使用してデイバスの種類を検出する方法です。これらのライブラリは、CSS メディアクエリと機能検出 (タッチ対応など) の一定の組み合わせを使用するため、デバイスの種類を検出する信頼性の高い方法になります。Modernizr ライブラリを使用してデバイスの種類を検出する簡単な例については、http://www.html5rocks.com/static/demos/cross-device/feature/index.htmlを参照してください。Device.js ライブラリを使用して Visualforce と統合する包括的な例については、GitHub リポジトリ(https://github.com/sbhanot-sfdc/Visualforce-Device.js) を参照してください。このリポジトリの DesktopVersion.page から抜粋したスニペットを次に示します。

<apex:page docType="html-5.0" sidebar="false" showHeader="false" standardStylesheets="false"cache="false" >

<head><!-- Every version of your webapp should include a list of allversions. --><link rel="alternate" href="/apex/DesktopVersion" id="desktop"media="only screen and (touch-enabled: 0)"/>

<link rel="alternate" href="/apex/PhoneVersion" id="phone"media="only screen and (max-device-width: 640px)"/>

<link rel="alternate" href="/apex/TabletVersion" id="tablet"media="only screen and (min-device-width: 641px)"/>

<meta name="viewport" content="width=device-width, user-scalable=no"/><script src="{!URLFOR($Resource.Device_js)}"/>

</head>

<body><ul><li><a href="?device=phone">Phone Version</a></li><li><a href="?device=tablet">Tablet Version</a></li>

</ul><h1> This is the Desktop Version</h1>

</body></apex:page>

上記のスニペットは、アプリケーションでサポートするデバイスの種類ごとに <link>タグを簡単に追加できることを示しています。Device.js ライブラリが、検出されたデバイスの種類に基づいて自動的にユーザを適切なVisualforceページにリダイレクトします。また、上記の「?device=xxx」という形式を使用して、デフォルトの Device.js リダイレクトを上書きする方法もあります。

サーバ側でのデバイス検出もう 1 つのオプションは、サーバ上 (Apex コントローラや拡張クラスなど) でデバイスの種類を検出する方法です。サーバ側でのデバイス検出は、ユーザエージェント HTTP ヘッダーの解析に基づきます。次に、Visualforce

ページが iPhone クライアントから参照されているかどうかを検出できる方法を示す簡単なコードスニペットを示します。<apex:page docType="html-5.0"

sidebar="false"showHeader="false"cache="false"

153

マルチデバイス戦略HTML5 およびハイブリッド開発

standardStylesheets="false"controller="ServerSideDeviceDetection"action="{!detectDevice}">

<h1> This is the Desktop Version</h1></apex:page>

public with sharing class ServerSideDeviceDetection {public boolean isIPhone {get;set;}public ServerSideDeviceDetection() {

String userAgent =System.currentPageReference().

getHeaders().get('User-Agent');isIPhone = userAgent.contains('iPhone');

}public PageReference detectDevice(){

if (isIPhone)return Page.PhoneVersion.setRedirect(true);

elsereturn null;

}}

上記のコードスニペットのユーザエージェント解析は、包括的ではないため、正規表現マッチングに基づいてサポートする必要があるすべてのデバイスを検出するより堅牢な機能を実装する必要があります。手始めに、detectmobilebrowsers.com のコードスニペットに含まれる正規表現を確認することをお勧めします。

数種のデバイスを適切にサポートする Force.com アプリケーションをどのように設計するか?サポートする必要のあるデバイスと、そのデバイスの判別方法が決まったら、デバイスやフォーム要素ごとにカスタマイズされたユーザ操作性を提供する最適なアプリケーション設計を考えます。ここでもいくつかのオプションを検討します。同一の Visualforce ページを各種のフォーム要素で適切に表示させるだけでよいシンプルなアプリケーションの場合は、応答性の高い設計アプローチが効果的なオプションです。簡単に言うと、応答性の高い設計では、CCS3 メディアクエリを使用し、クライアントブラウザのフォーム要素に合わせてページの書式を動的に再設定します。Twitter Bootstrap のような応答性の高い設計フレームワークもこの用途に使用できます。もう 1 つのオプションは、複数の Visualforce ページを設計し、特定のフォーム要素ごとに各ページを最適化してから、前のセクションで説明したいずれかの手法を使用してユーザを適切なページにリダイレクトする方法です。個別の Visualforce ページを用意するからといって、コードや機能が重複するわけではなく、また重複すべきでもありません。適切に設計されたソリューションでは、クライアント側 (コンポーネントやテンプレートなど Visualforce の戦略を使用する) とサーバ側 (たとえば、共通のビジネスロジックを Apex クラスにカプセル化して複数のページコントローラからコールできるようにする) の両方でコードを最大限に再利用できます。こうした設計の優れた例は、前述のオープンソースの Contact Viewer アプリケーションで確認できます。このアプリケーションはスマートフォン向け (ContactsAppMobile.page) とタブレット向け (ContactsApp.page)

に異なるページを用意していますが、両方が共通のテンプレート (MobileAppTemplate.page) を共有しているため、コードやアイテムが最大限に再利用されています。下の図は、Contact Viewer アプリケーションの設計上の概念を示しています。

154

マルチデバイス戦略HTML5 およびハイブリッド開発

また、1 つのVisualforceページを複数のフォーム要素に対応させることも可能です。この場合は、サーバ側でデバイスの検出を行い、ほとんどの Visualforceコンポーネント (具体的には、<div> タグの CSS「display:none/block」プロパティ) で使用可能な「rendered」属性を利用して、ページ要素を選択的に表示または非表示にします。ただし、このアプローチはコードが膨大になり、管理が困難になる可能性があるため、慎重に使用する必要があります。

HTML5 開発ツール

最近の Web 開発者は、アプリケーション開発サイクルを迅速化するためにオープンソースツールを頻繁に活用しています。これらのツールを使用すると、HTML5 コーディングを大幅に簡略化できます。たとえば、Salesforce

対応のアプリケーションを数時間で作成するために、Google の Polymer フレームワークを Force.com JavaScript ライブラリと組み合わせることができます。Salesforceでは、これと同様に機能するベータのオープンソースライブラリ (モバイル UI 要素) を提供しています。モバイル UI 要素を確認したり、使用を開始したりするには、「Polymer を使用するモバイル UI 要素」を参照してください。

Visualforce を使用した HTML5 コンテンツの配信

デスクトップ環境用にカスタム Web サイトを作成するには、従来より Visualforce を使用しています。ただし、HTML5 と組み合わせると、Visualforce がモバイル Web アプリケーションで実行できる配信メカニズムになりま

155

HTML5 開発ツールHTML5 およびハイブリッド開発

す。これらのアプリケーションでは、Sencha のようなサードパーティの UI ウィジェットライブラリや、AngularJS

および Backbone.js などのテンプレートフレームワークを活用して、Salesforce 内のデータにバインドできます。HTML5 Apexページを設定するには、docType属性を「html-5.0」に変更し、次のような他の設定を使用します。<apex:page docType="html-5.0" sidebar="false" showHeader="false" standardStylesheets="false"cache="true" >

</apex:page>

このコードは、HTML5 コンテンツを含めることができるApexページを設定しますが、作成されるのは空のページです。静的リソースとサードパーティのライブラリを使用することで、HTML と JavaScript のコードを追加して、完全に対話形式のモバイルアプリケーションを構築できます。

Salesforce データへのアクセス: コントローラと API

HTML5 アプリケーションでは、2 通りの方法で Salesforce データにアクセスできます。• JavaScript Remoting を使用して、Apex コントローラを呼び出す。• forcetk.mobilesdk.js を使用して Salesforce API にアクセスする。

JavaScript Remoting を使用した Apex コントローラの呼び出しApexでは、JavaScript からApexコントローラメソッドを呼び出す方法として次の 2 つがサポートされています。• apex:actionFunction

• JavaScript Remoting

どちらの手法も AJAX 要求を使用して JavaScript から Apex コントローラメソッドを直接呼び出します。JavaScript

コードは Visualforce ページ上でホストする必要があります。apex:actionFunction に比べて、JavaScript Remoting には、いくつかの利点があります。• apex:actionFunction に比べて柔軟性に富み、パフォーマンスが高い。• Apex コントローラメソッドでパラメータと戻り値の型がサポートされ、Apex と JavaScript 間でデータ型の対

応付けが自動的に行われる。• コールバックで非同期処理モデルを使用する。• apex:actionFunction と異なり、AJAX 要求に Visualforce ページのビューステートが含まれない。この結

果、往復速度が速くなります。ただし、apex:actionFunctionに比べて、JavaScript Remotingではより多くのコードを作成する必要があります。次の例では、Visualforce ページの <script> タグに JavaScript コードを挿入しています。このコードは、Visualforce

Remoting マネージャオブジェクトで invokeAction() メソッドをコールします。Apex コントローラオブジェクト objName で getItemId() という名前の関数をコールするのに必要なメタデータを invokeAction()

に渡します。invokeAction()は非同期で実行されるため、getItemId()から返される値を処理するコール

156

Salesforce データへのアクセス: コントローラと APIHTML5 およびハイブリッド開発

バック関数もコードで定義します。Apexコントローラでは、@RemoteActionアノテーションにより、外部のJavaScript コードに getItemId() 関数が公開されます。//Visualforce page code<script type="text/javascript">

Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.MyController.getItemId}',objName,function(result, event){

//process response here},{escape: true}

);<script>

//Apex Controller code

@RemoteActionglobal static String getItemId(String objectName) { ... }

@RemoteAction アノテーションについての詳細は、https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_RemoteAction.htmを参照してください。

ForceTK および jQuery を使用した Salesforce API へのアクセス次のコードサンプルでは、ユーザインターフェースに jQuery Mobile ライブラリを使用しています。このコードを実行するには、Visualforce ページに jQuery および ForceTK ライブラリが含まれている必要があります。これらのリソースを追加する手順は、次のとおりです。1. app.js、forcetk.mobilesdk.js、jquery.js、およびプロジェクトに必要な他の静的リソースを含む、

ZIP ファイルなどのアーカイブファイルを作成します。2. Salesforce で、[あなたの名前] > [アプリケーションの設定] > [開発] > [静的リソース] からアーカイブファイル

をアップロードします。jQuery Mobile ライブラリのインスタンスを取得すると、サンプルコードで ForceTK クライアントオブジェクトが作成され、セッション ID を使用して初期化されます。次に非同期の ForceTK query()メソッドをコールして、SOQL クエリが処理されます。クエリのコールバック関数では、jQuery Mobile を使用して、クエリから返された最初の Name 項目が、「accountname」という ID のオブジェクトに HTML として表示されます。Apex ページの最後では、HTML5 コンテンツにより accountname 要素が単純な <span> タグとして定義されます。<apex:page>

<apex:includeScriptvalue="{!URLFOR($Resource.static,

'jquery.js')}" /><apex:includeScript

value="{!URLFOR($Resource.static,'forcetk.mobilesdk.js')}" />

<script type="text/javascript">// Get a reference to jQuery// that we can work with$j = jQuery.noConflict();

157

Salesforce データへのアクセス: コントローラと APIHTML5 およびハイブリッド開発

// Get an instance of the REST API client// and set the session IDvar client = new forcetk.Client();client.setSessionToken(

'{!$Api.Session_ID}');

client.query("SELECT Name FROM Account LIMIT 1",function(response){

$j('#accountname').html(response.records[0].Name);

});</script><p>The first account I see is

<span id="accountname"></span>.</p></apex:page>

メモ:

• Visualforce ページからであっても REST API を使用すると、API コールが使用されます。• Mobile SDK コンテナまたは Cordova Web ビューから行う SalesforceAPI コールには、プロキシサービスは必

要ありません。Cordova Web ビューでは同じ発生元のポリシーが無効になるため、API コールを直接行うことができます。この免除は、すべての Mobile SDK ハイブリッドアプリケーションとネイティブアプリケーションに適用されます。

追加オプションHTML5 アプリケーションでは、SmartSync Data Framework を使用できます。必要な JavaScript ライブラリを静的リソースとして含めるだけで十分です。モデルおよび転送機能を利用してください。この場合、オフラインアクセスは無効になります。「SmartSync を使用した Salesforce オブジェクトへのアクセス」を参照してください。Salesforce Developer Marketing には、開発者向けに HTML5 アプリケーションのクイックスタートに役立つモバイルパックが用意されています。

オフラインの制限事項Force.com で HTML5 をオフラインで使用する場合のヒントについては、次の記事を参照してください。• https://developer.salesforce.com/blogs/developer-relations/2011/06/using-html5-offline-with-forcecom.html

• http://developer.salesforce.com/blogs/developer-relations/2013/03/using-javascript-with-force-com.html

ハイブリッドアプリケーションのクイックスタート

ハイブリッドアプリケーションは、Salesforce Mobile SDK を活用しながら、容易に操作できる JavaScript およびHTML5 を使用して開発できます。ハイブリッドアプリケーション開発の概念を理解している場合は、次の手順を使用してすばやく開発を開始できます。

158

ハイブリッドアプリケーションのクイックスタートHTML5 およびハイブリッド開発

1. Android のアプリケーション開発には、次の前提条件があります。• Java JDK 7 以降 — www.oracle.com/downloads。• Node Package Manager (npm) — SalesforceMobileSDK-Android リポジトリへの直接アクセスを含む、すべての

Android 開発シナリオでインストールする必要があります。• Android Studio 2 以降 — developer.android.com/sdk。• Android SDK および Android SDK Tools — Android Studio 内からインストールします。

a. Android Studio メニューで、[ツール] > [Android] > [SDK Manager] をクリックします。b. [SDK Platforms] タブをクリックします。c. 少なくとも次の必須 SDK レベルとすべての中間レベルをインストールします。

– 最小限の API: Android KitKat (API 19)

– 対象の API: Android Marshmallow (API 23)

d. [SDK Tools] タブをクリックします。e. 最新バージョンの Android SDK Tools をインストールします。

• Android 仮想デバイス (AVD) — Android Studio 内からインストールします。a. Android Studio メニューで、[ツール] > [Android] > [AVD マネージャ] をクリックします。b. [仮想デバイスを作成...] をクリックします。c. Android KitKat (API 19)以上を対象とする AVD を少なくとも 1 つインストールします。Android Studioで AVD

を設定する方法については、developer.android.com/guide/developing/devices/managing-avds.htmlの手順を参照してください。

2. iOS のアプリケーション開発には、次の前提条件があります。• Xcode — バージョン 7 以降 (最新バージョンを推奨)。• iOS 8 以降。• 接続アプリケーションが存在する Salesforce Developer Edition 組織。

3. Mobile SDK をインストールします。• Android のインストール• iOS のインストール

4. まだ接続アプリケーションがない場合は、「接続アプリケーションの作成」を参照してください。OAuth 範囲として api、web、および refresh_token を選択します。

メモ: コールバック URL を指定する場合、実際のアドレスを使用する必要はありません。myapp:///mobilesdk/oauth/done など、URL に似た任意の値を使用してください。

5. ハイブリッドアプリケーションを作成します。• 「ハイブリッドアプリケーションを作成する」の手順を実行します。アプリケーション種別として

hybrid_local を使用します。

6. 新しいアプリケーションを実行します。

159

ハイブリッドアプリケーションのクイックスタートHTML5 およびハイブリッド開発

Android でハイブリッドアプリケーションを作成および実行する•

• iOS でハイブリッドアプリケーションを実行する

ハイブリッドアプリケーションの作成

ハイブリッドアプリケーションは、HTML5 Web アプリケーションの開発の容易さと、ネイティブプラットフォームの機能とを統合したものです。これらは、Salesforce Mobile コンテナ (アプリケーションをデバイス固有のコードに変換するネイティブレイヤ) 内で実行され、その機能は HTML5 と JavaScript ファイルで定義します。これらのアプリケーションは、次の 2 つのカテゴリのいずれかになります。• ハイブリッドローカル — forcetk.mobilesdk.js ライブラリを使用して開発されたハイブリッドアプリ

ケーションが Mobile コンテナ内に Web アプリケーションをラップします。これらのアプリケーションは、その HTML、JavaScript、および CSS ファイルをデバイス上に保存します。

• ハイブリッドリモート — Visualforceテクノロジを使用して開発されたハイブリッドアプリケーションが Mobile

コンテナを介して Apex ページを配信します。これらのアプリケーションは、その HTML、JavaScript、およびCSS ファイルの一部または全部を Salesforce サーバまたはデバイス上 (の http://localhost) に保存します。

HTML および JavaScript コードを提供するだけでなく、対象プラットフォームで最小限のコンテナアプリケーションを保守することも必要です。これらのアプリケーションは、必要に応じて設定するネイティブテンプレートと似ています。他の開発者が使用するためにライブラリまたはサンプルアプリケーションを作成している場合は、GitHub などのバージョン管理されるオンラインリポジトリに公開モジュールを投稿することをお勧めします(https://github.com)。スニペットなどの小規模なサンプル用に、GitHub にはオーバーヘッドの低い共有フォーラムである gist が用意されています (https://gist.github.com)。

ハイブリッド開発についてハイブリッドアプリケーションを Mobile SDK コンテナで開発する場合、変更後にリコンパイルとリビルドが必要になります。ブラウザで JavaScript 開発を行う方が容易です。コードを変更した後、ブラウザを更新するだけで変更内容を確認できます。この理由により、ハイブリッドアプリケーションはブラウザで直接開発し、テストの最終段階でのみコンテナでコードを実行することをお勧めします。開発者ツールが組み込まれている Google Chrome などのブラウザで開発することをお勧めします。これらのツールでは、実行時に Web アプリケーションのシンボルおよびコードにアクセスできます。

Cordova を使用したハイブリッドアプリケーションの開発Salesforce Mobile SDK 4.3 には、プラットフォームごとに特定のバージョンの Apache Cordova (iOS の場合は 4.2.0、Android の場合は 5.0.0)を使用するハイブリッドコンテナが用意されています。アーキテクチャ上、Mobile SDKハイブリッドアプリケーションは、Salesforce Mobile SDK を Cordova プラグインとして使用する Cordova アプリケーションです。Cordova には、アプリケーションのプラグインを更新するための単純なコマンドラインツールが用意されています。Cordova の利点についての詳細は、https://cordova.apache.org/を参照してください。

160

ハイブリッドアプリケーションの作成HTML5 およびハイブリッド開発

ハイブリッドアプリケーションを作成するまず、「Android および iOS の開発の前提条件」 (ページ 18)に記載されている要件を満たしていることを確認します。Mobile SDKハイブリッドアプリケーションを作成するには、forceios または forcedroid ユーティリティと Cordova コマンドラインを使用します。1. コマンドプロンプトまたはターミナルウィンドウを開きます。2. Cordova コマンドライン (バージョン 5.4.0 以降) をインストールします。

sudo npm -g install cordova

メモ: 「参照・更新」権限がない場合、Mac OS X では sudo コマンドが必要になります。Windows にインストールする場合は、sudo コマンドを省略します。

3. 対象プラットフォームの手順に従います。

iOS の場合:Android の場合:

a. forceios npm パッケージをインストールします。すでに forceios の旧バージョンがインストールさ

a. forcedroid npm パッケージをインストールします。すでに forcedroid の旧バージョンがインストールされている場合、再インストールする必要があります。

れている場合、再インストールする必要があります。

b. コマンドプロンプトまたはターミナルウィンドウで、forcedroid create を実行します。ア

b. コマンドプロンプトまたはターミナルウィンドウで、forceios createを実行します。アプリケーション種別の入力を要求されたら、次のように指定します。

プリケーション種別の入力を要求されたら、次のように指定します。

• hybrid_local (ローカルプロジェクトにコードを保存するハイブリッドアプリケーションの場合)。

• hybrid_local (ローカルプロジェクトにコードを保存するハイブリッドアプリケーションの場合)。

• hybrid_remote (サーバの Visualforce アプリケーションのコードを含むハイブリッドアプリケーションの場合)。

• hybrid_remote (サーバの Visualforce アプリケーションのコードを含むハイブリッドアプリケーションの場合)。

•• Facebook の React Native フレームワークを使用するハイブリッドローカルアプリケーションに react_native を指定します。

Facebook の React Native フレームワークを使用するハイブリッドローカルアプリケーションに react_native を指定します。

c.c. (ハイブリッドリモートアプリケーションのみ)

forceios から開始ページの入力を要求されたら、(ハイブリッドリモートアプリケーションのみ)

forcedroid から開始ページの入力を要求されたら、Apex ランディングページのスラッシュ (「/」) で始まる相対 URL を指定します。

Apex ランディングページのスラッシュ (「/」) で始まる相対 URL を指定します。

4. HTML、JavaScript、CSS、bootconfig.json ファイルをインポートする場合、これらのファイルをプロジェクトディレクトリの ${target.dir}/www/ ディレクトリに配置します。

161

Cordova を使用したハイブリッドアプリケーションの開発

HTML5 およびハイブリッド開発

重要: cordova.js、cordova.force.js、Cordova プラグインを含めないでください。

5. (forcedroid のみ) プロジェクトディレクトリで、UTF-8 に準拠しているテキストエディタでwww/bootconfig.json ファイルを開き、次のプロパティの値を置き換えます。• remoteAccessConsumerKey — デフォルト値を新しい接続アプリケーションからのコンシューマキー

に置き換えます• oauthRedirectURI — デフォルト値を新しい接続アプリケーションからのコールバック URL に置き換

えます

6. cd を実行してプロジェクトディレクトリ (<target_directory>/<application_name>) に移動します。7. 次のように入力します。

npm install [email protected]

8. さらにプラグインを追加する場合、次のコマンドを入力して Salesforce Cordova プラグインを一時的に削除します。cordova plugin remove com.salesforce

9. Cordova プラグインごとに、次のように入力します。cordova plugin add <plug-in repo or plug-in name>

メモ: https://plugins.cordova.io に移動して使用可能なプラグインを検索します。

10. 最後のプラグインを追加したら、次のコマンドを入力して Salesforce Cordova プラグインを再度追加します。cordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugin

11. (省略可能) iOS サポートを Android ハイブリッドアプリケーションに追加するには、次のように入力します。cordova platform add [email protected]

このステップでは、アプリケーションディレクトリに platforms/iosディレクトリを作成してから、ios

ディレクトリに Xcode プロジェクトを作成します。Xcode プロジェクトには、アプリケーションに追加したプラグインが含まれます。

12. (省略可能) Android サポートを iOS ハイブリッドアプリケーションに追加するには、次のように入力します。cordova platform add [email protected]

このステップでは、アプリケーションディレクトリに platforms/android ディレクトリを作成してから、android ディレクトリに Android Studio プロジェクトを作成します。このプロジェクトには、アプリケーションに追加したプラグインが含まれます。

13. 次のように入力します。cordova prepare

Web アセットを、www/ディレクトリの下にあるそれぞれのプラットフォーム固有ディレクトリにリリースします。

162

Cordova を使用したハイブリッドアプリケーションの開発

HTML5 およびハイブリッド開発

重要: リリース時、www/ ディレクトリの内容を変更した後は必ず cordova prepareを実行して、変更をプラットフォーム固有のプロジェクトフォルダにリリースします。

Cordova コマンドラインについての詳細は、Cordova 3.5 のドキュメントで「Command-Line Interface」を参照してください。

Android でハイブリッドアプリケーションを作成および実行する作成する前に、Android SDK と少なくとも 1 つの Android エミュレータを含む Android Studioがインストール済みであることを確認してください。Mobile SDKの Android 要件を参照して、正しいバージョンの Android コンポーネントをインストールしてください。cordova prepare を実行したら、プロジェクトを作成して実行します。アプリケーションを Android Studio で実行する手順は、次のとおりです。1. Android Studio を起動します。2. ようこそ画面から [Import Project (Eclipse ADT, Gradle, etc.) (プロジェクトをインポート (Eclipse ADT、Gradle な

ど))]を選択します。または、Android Studio がすでに実行されている場合は、[File (ファイル)] > [New (新規)] >

[Import Project (プロジェクトをインポート)] を選択します。3. <your_target_dir>/<your_app_name>/platforms/android を選択して、[OK] をクリックします。4. ビルドが終了したら、android ターゲットを選択して、メニューまたはツールバーの [Run ‘android’

(「android」を実行)] をクリックします。接続されている Android デバイスまたはエミュレータを選択します。

重要:

• Android Studio から Gradle ラッパーのバージョンを修正するように求められたら、[Fix It (修正)] ボタンをクリックします。プロセスが完了したら、Android Studio によってプロジェクトが自動的に再インポートされます。

• Android Studio の構築が次のエラーで失敗した場合、Error:Execution failed for task ':processDebugManifest'. > Manifest merger failedwith multiple errors, see logs

アプリケーションの android/manifests/AndroidManifest.xml ファイルを開き、次のテキストに完全に一致する行を削除して、再構築します。<activity android:exported="true"android:name="com.adobe.phonegap.push.PushHandlerActivity" />

iOS でハイブリッドアプリケーションを実行するcordova prepare を iOS ハイブリッドアプリケーションで実行したら、Xcode でプロジェクトを開き iOS シミュレータでアプリケーションを実行できます。アプリケーションを Xcode で実行する手順は、次のとおりです。1. Xcode で [File (ファイル)] > [Open (開く)] を選択します。

163

Cordova を使用したハイブリッドアプリケーションの開発

HTML5 およびハイブリッド開発

2. 新しいアプリケーションのディレクトリの platforms/ios/ ディレクトリに移動します。3. <アプリケーション名>.xcodeproj ファイルをダブルクリックします。4. 左上隅にある [Run (実行)] ボタンをクリックするか、COMMAND-R キーを押します。

ハイブリッドリモートアプリケーションの開発ハイブリッドリモートアプリケーションのためにサーバで cordova.js やプラグインをホストする必要がなくなります。代わりに、HTML ソースに cordova.js を https://localhost/cordova.js として追加できます。次に例を示します。<script src="https://localhost/cordova.js"></script>

また、すべての CSS および JavaScript リソースに https://localhost を使用することもできます。その後、それらのファイルを、サーバから配信するのではなくアプリケーションと一緒にバンドルできます。この方法により、ハイブリッドリモートアプリケーションを Visualforce と Apex で開発できるうえに、パフォーマンスも大幅に向上します。

メモ:

• Mobile SDK 2.3 以降では、ハイブリッドリモートアプリケーションの https://localhost が自動的にホワイトリストに登録されます。以前のバージョンの Mobile SDK で開発されたアプリケーションの場合、手動で https://localhost を config.xml ファイルにホワイトリスト登録できます。

• https://localhost を使用してソースファイルを追加する Visualforce ページは、Salesforce Mobile SDK

コンテナアプリケーションでのみ機能します。ページを Web ブラウザでも動作させるには、Apex でユーザエージェントを調べ、クライアントが Mobile SDK コンテナかどうかを検出します。検出結果に基づいて、適切な script include タグを使用します。

例: ハイブリッドローカルアプリケーションの FileExplorer SDK サンプル(https://github.com/forcedotcom/SalesforceMobileSDK-Shared/tree/unstable/samples/fileexplorer) は、簡単にハイブリッドリモートアプリケーションに変換できます。アプリケーションを変換するには、メイン HTML ページをサーバから配信されるVisualforceページとして再定義します。次に、CSS および JavaScript リソースをアプリケーションと一緒にバンドルして、デバイスに保存されるようにします。Visualforce ページから開始しましょう。1. Salesforce Developer Edition 組織の場合、次の属性を持つ Visualforce ページを「FileExplorer」という名前で作

成します。<apex:page docType="html-5.0" showHeader="false" sidebar="false"><!-- Paste content of FileExplorer.html here, but remove the “<!DOCTYPE html>”directive --></apex:page>

2. samples/fileexplorer/FileExplorer.html ファイルのコンテンツを FileExplorer の Visualforce ページにコピーします。

3. 挿入したコンテンツの上部にある <!DOCTYPE html> ディレクティブを削除します。

164

ハイブリッドリモートアプリケーションの開発HTML5 およびハイブリッド開発

4. CSS ファイルへのすべての参照を、https://localhost から読み込まれるように更新します。置換前:

<link rel="stylesheet" href="css/styles.css"/><link rel="stylesheet" href="css/ratchet.css"/>

置換後:

<link rel="stylesheet" href="https://localhost/css/styles.css"/><link rel="stylesheet" href="https://localhost/css/ratchet.css"/>

5. すべてのスクリプト参照についてステップ 3 を繰り返します。置換前の参照は、次のとおりです。<script src="js/jquery.min.js"></script><script src="js/underscore-min.js"></script><script src="js/backbone-min.js"></script><script src="js/forcetk.mobilesdk.js"></script><script src="cordova.js"></script><script src="js/smartsync.js"></script><script src="js/fastclick.js"></script><script src="js/stackrouter.js"></script><script src="js/auth.js"></script>

置換後:

<script src="https://localhost/js/jquery.min.js"></script><script src="https://localhost/js/underscore-min.js"></script><script src="https://localhost/js/backbone-min.js"></script><script src="https://localhost/js/forcetk.mobilesdk.js"></script><script src="https://localhost/cordova.js"></script><script src="https://localhost/js/smartsync.js"></script><script src="https://localhost/js/fastclick.js"></script><script src="https://localhost/js/stackrouter.js"></script><script src="https://localhost/js/auth.js"></script>

6. 作業を保存します。ここでは、サンプルアプリケーションのラッパーを作成し、ハイブリッドリモートアプリケーションに変換します。1. ターミナルウィンドウまたはコマンドプロンプトで、次のコマンドを実行します。

cordova create fileexplorercd fileexplorernpm install [email protected] plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugincordova platform add [email protected] -RL /<local_path_to>/SalesforceMobileSDK-Shared/samples/fileexplorer/* www/

2. テキストエディタで、新しいプロジェクトの fileexplorer/www/bootconfig.json を開き、変更します。"isLocal": true,"startPage": "FileExplorer.html",

165

ハイブリッドリモートアプリケーションの開発HTML5 およびハイブリッド開発

変更後"isLocal": false,"startPage": "/apex/FileExplorer",

3. ターミナルウィンドウまたはコマンドプロンプトに戻り、次のコマンドを入力します。cordova prepare

完了しました。<local_repo>/ samples/fileexplorer/platforms/android フォルダを Android

Studio にインポートして、アプリケーションを実行できるようになりました。このサンプルをテストするときは、必ず Visualforce ページを作成した組織にログインしてください。

メモ: Android プラットフォームのバージョン (この例では 5.0.0) は、Mobile SDK の現在のバージョンによって異なります。これは、Mobile SDK バージョン 4.1.2 以降で変更される可能性があります。

ハイブリッドサンプルアプリケーションSalesforce Mobile SDK には、JavaScript での Mobile SDK 機能の使用方法を示すハイブリッドサンプルが備えられています。ハイブリッドサンプルは、次の 2 つの方法で提供されます。• ネイティブラッパーを使用するプラットフォーム固有のアプリケーションとして。これらのラッパーは、

ハイブリッドサンプルの一部のサブセットに提供されます。iOS サンプルには、SalesforceMobileSDK-iOS GitHub

リポジトリのルートディレクトリにある Mobile SDK ワークスペース (SalesforceMobileSDK.xcodeproj)

からアクセスできます。また、Android サンプルには、SalesforceMobileSDK-Android リポジトリのhybrid/SampleApps ディレクトリからアクセスできます。

• HTML5、JavaScript、CSS ソースコードのみが含まれる、プラットフォームに依存しない Web アプリケーションとして。これらのアプリケーションには、すべてのハイブリッドサンプルが含まれていて、プラットフォーム固有のハイブリッドアプリケーションの基盤が提供されます。これらのサンプルアプリケーションは、SalesforceMobileSDK-Shared GitHub リポジトリからダウンロードし、Cordova コマンドラインを使用して作成できます。

Android ハイブリッドサンプルラッパー• AccountEditor: smartsync.js ライブラリを使用してオフラインデータを同期する方法について説明しま

す。• NoteSync: 非 REST API を使用して Salesforce のメモを取得する方法を示します。• SmartSyncExplorerHybrid: SmartSync プラグインを使用してオフラインデータを同期する方法について説明し

ます。

iOS ハイブリッドサンプルラッパー• AccountEditor: smartsync.js ライブラリを使用してオフラインデータを同期する方法について説明しま

す。• NoteSync: 非 REST API を使用して Salesforce のメモを取得する方法を示します。

166

ハイブリッドサンプルアプリケーションHTML5 およびハイブリッド開発

• SmartSyncExplorerHybrid: SmartSync プラグインを使用してオフラインデータを同期する方法について説明します。

ハイブリッドサンプルアプリケーション (ソースのみ)Salesforce Mobile SDK では、SalesforceMobileSDK-Shared GitHub リポジトリでプラットフォームに依存しない次のハイブリッドサンプルアプリケーションが提供されます。• accounteditor: SmartSync Data Framework を使用して Salesforce データにアクセスします。• contactexplorer: Cordova を使用してローカルデバイスの取引先責任者を取得します。また、

forcetk.mobilesdk.js ツールキットを使用して、Salesforce REST API で REST トランザクションを実装します。アプリケーションでは、Salesforce SDK の OAuth2 サポートを使用して OAuth ログイン情報を取得し、JavasScript イベントを送信することによって、そのログイン情報を forcetk.mobilesdk.js に伝搬します。

• fileexplorer: Files API を示します。• notesync: 非 REST API を使用して Salesforce のメモを取得します。• simplesyncreact:: SmartSync プラグインを使用する React Native アプリケーションのデモを実施します。• smartstoreexplorer: SmartStore API を探索できます。• smartsyncexplorer: SmartSyncプラグインではなく smartsync.jsを使用してオフライン同期を行うデモを実

施します。• userandgroupsearch: グループのユーザを検索できます。• userlist: 組織のユーザをリストします。これは、最も単純なハイブリッドサンプルアプリケーションです。• usersearch: 組織のユーザを検索できます。• vfconnector: ネイティブコンテナ内の Visualforce ページをラップします。この例では、BasicVFTest という

Visualforceページが組織に存在することを想定しています。アプリケーションではまず、Salesforce SDK OAuth2

サポートを使用して OAuth のログイン情報を取得し、そのログイン情報を使用して、Visualforce ページにアクセスするための適切な Web ビュー Cookie を設定します。

ハイブリッドサンプルアプリケーションを作成するSalesforceMobileSDK-Shared リポジトリの samples ディレクトリからハイブリッドアプリケーションを作成するには、forcedroid または forceios と Cordova コマンドラインを使用します。hybrid_localまたは hybrid_remote

アプリケーションを作成し、共有リポジトリから Web アセット (HTML、JavaScript、CSS ファイル) およびbootconfig.json ファイルを追加します。

メモ: ContactExplorer サンプルには cordova-plugin-contactsおよび cordova-plugin-statusbarプラグインが必要です。他のハイブリッドサンプルアプリケーションには、特殊な Cordova プラグインは必要ありません。

サンプルアプリケーションを作成する手順は、次のとおりです。1. コマンドプロンプトまたはターミナルウィンドウを開きます。2. 共有リポジトリをコピーします。

git clone https://github.com/forcedotcom/SalesforceMobileSDK-Shared

167

ハイブリッドサンプルアプリケーションHTML5 およびハイブリッド開発

3. forcedroid または forceios を使用して、アプリケーションを作成します。type に、「hybrid_local」と入力します。

4. 新しいアプリケーションのディレクトリに変更します。cd <app_target_directory>

5. 次のように入力します。npm install [email protected]

6. ContactExplorer サンプルアプリケーションを作成している場合は、Salesforce プラグインを削除し、必須のCordova プラグインを追加してから Salesforce プラグインを再度追加します。cordova plugin remove com.salesforcecordova plugin add cordova-plugin-contactscordova plugin add cordova-plugin-statusbarcordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugin

7. Android サポートを forceios プロジェクトに追加するには、次のように入力します。cordova platform add [email protected]

8. (Mac のみ) iOS サポートを forcedroid プロジェクトに追加するには、次のように入力します。cordova platform add [email protected]

9. サンプルソースファイルを新しいプロジェクトディレクトリの www フォルダにコピーします。Mac の場合:

cp -RL <local path to SalesforceMobileSDK-Shared>/SampleApps/<template>/* www/

Windows の場合:

copy <local path to SalesforceMobileSDK-Shared>\SampleApps\<template>\*.* www

既存のファイルを上書きするかどうかたずねられたら、上書きに同意します。10. Cordova の最終準備を実行します。

cordova prepare

メモ:

• Android Studio では、プラットフォーム名 (「android」) で forcedroid ハイブリッドプロジェクトを参照します。たとえば、プロジェクトを実行するには、スタートアッププロジェクトとして「android」を選択し、[Run (実行)] をクリックします。

• Windows の場合、Android Studio では、デフォルトプロジェクトエンコードが windows-1252 に設定されます。この設定は、forcedroid Gradle ビルドファイルの UTF-8 エンコードと競合します。最良の結果を得るには、デフォルトプロジェクトエンコードを UTF-8 に変更します。

• Windows では、必ずシステム管理者として Android Studio を実行します。

168

ハイブリッドサンプルアプリケーションHTML5 およびハイブリッド開発

ContactExplorer ハイブリッドサンプルの実行Mobile SDK に含まれている ContactExplorer サンプルアプリケーションを見てみましょう。この練習は、Mac OS または Windows で実行できますが、完全に iOS ターゲットを検証できるのは Mac のみです。この練習を開始する前に、次のディレクトリがあることを確認してください。• SalesforceMobileSDK-Sharedのコピーしたリポジトリを格納するディレクトリ (ルートディレクトリま

たは簡単にアクセスできる場所にあるその他のディレクトリ)。• Mobile SDKハイブリッドアプリケーションを作成および開発するためのディレクトリ。Cordova プロジェクト

には Android ターゲットと iOS ターゲットの両方を含めることができるため、プラットフォームに依存しないディレクトリに配置することをお勧めします。

メモ: この単元の Cordova コマンドを実行する前に、Apache Ant がインストール済みでシステムパスに追加されていることを確認します。

このサンプルアプリケーションのソースコードは GitHub にあるため、まず共有リポジトリをコピーします。1. コマンドプロンプトまたはターミナルウィンドウを開きます。2. 共有リポジトリをコピーします。

git clone https://github.com/forcedotcom/SalesforceMobileSDK-Shared

3. 次のスクリプトを実行します。このスクリプトは Mac 互換ですが Windows でも容易に実行できます。そのためには、cp -RL ではなく Windows の copy コマンドを使用します。さらに、Windows 互換ではないcordova platform add ios コマンドを削除します。cordova create contactsApp com.salesforce.contactexplorer contactsAppcd contactsAppnpm install [email protected] plugin add cordova-plugin-contactscordova plugin add cordova-plugin-statusbarcordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugincordova platform add [email protected] platform add [email protected] -RL <local path to SalesforceMobileSDK-Shared>/samples/contactexplorer/* www/cordova prepare

重要: SalesforceMobileSDK-CordovaPlugin は、必ず他のプラグインを追加した後で最後に追加してください。

このスクリプトでは iOS プロジェクトと Android プロジェクトを作成します。これらはどちらも ContactExplorer

サンプルアプリケーションをラップします。これで、いずれかのプラットフォームでアプリケーションを実行する準備ができました。iOS デバイスを使用する場合、developer.apple.com/libraryにある『Xcode User Guide』(Xcode

ユーザガイド) の説明に従ってシミュレータのプロファイルを設定する必要があります。同様に、Android デバイスは developer.android.com/tools の説明に従って設定する必要があります。アプリケーションを実行すると、初期スプラッシュ画面が表示された後でSalesforceログイン画面が表示されます。

169

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

Developer Edition 組織のユーザ名とパスワードを使用してログインします。アプリケーションから Salesforceデータにアクセスできるようにするには、[許可]をタップします。アプリケーションを実行している状態なので、取引先責任者と取引先のリストを取得できます。DE 組織からSalesforce取引先責任者名を取得するには [SFDC の取引先責任者を取得] をタップし、取引先名を取得するには [SFDC の取引先を取得] をタップします。

170

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

タップするごとに、行が無限のリストに追加されます。完全なリストを表示するには、スクロールダウンします。

171

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

アプリケーションの動作を詳しく見てみましょう。アプリケーションは、Salesforce リソースへのアクセスを試行する前に、Salesforce OAuth プラグイン上でgetAuthCredentials() をコールする必要があります。getAuthCredentials() に渡すカスタム更新関数(次の例では salesforceSessionRefreshed) とエラー関数を定義します。認証が成功すると、OAuth プラグインは、更新関数をコールし、セッションおよび更新トークンを渡します。アプリケーションは、これらのトークンを使用して forcetk.mobilesdk を初期化します。ContactExplorer サンプルアプリケーションにあるindex.html の次のコードは、ハイブリッドローカルアプリケーションでこのプロトコルを実装する方法を示しています。• アプリケーションは、onDeviceReady() 関数内で getAuthCredentials() をコールします。

cordova.require("com.salesforce.plugin.oauth").getAuthCredentials(salesforceSessionRefreshed,

getAuthCredentialsError);

• 認証が成功すると、OAuth プラグインは salesforceSessionRefreshed() 関数をコールします。// Global authenticated forcetk client instancevar forcetkClient;//...

function salesforceSessionRefreshed(creds) {cordova.require("com.salesforce.util.logger").

172

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

logToConsole("salesforceSessionRefreshed");

// Depending on how we come into this method, "creds" may// be callback data from the auth plugin, or an event fired// from the plugin.// The data is different between the two.var credsData = creds;// Event sets the "data" object with the auth data.if (creds.data)

credsData = creds.data;forcetkClient = new forcetk.Client(credsData.clientId,

credsData.loginUrl, null,cordova.require("com.salesforce.plugin.oauth").

forcetkRefresh);forcetkClient.setSessionToken(credsData.accessToken,

apiVersion, credsData.instanceUrl);forcetkClient.setRefreshToken(credsData.refreshToken);forcetkClient.setUserAgentString(credsData.userAgent);

}

ログインプロセスの完了後、サンプルアプリケーションに index.html (www フォルダ内) が表示されます。ページの読み込みが完了してモバイルフレームワークの準備ができたら、onDeviceReady() 関数によってregLinkClickHandlers() (inline.js 内) がコールされます。regLinkClickHandlers() によって、サ

ンプルアプリケーション内のさまざまな関数用にクリックハンドラが設定されます。たとえば、#link_fetch_sfdc_contacts ハンドラは、 forcetkClient オブジェクトを使用してクエリを実行します。$j('#link_fetch_sfdc_contacts').click(function() {

logToConsole("link_fetch_sfdc_contacts clicked");forcetkClient.query("SELECT Name FROM Contact",

onSuccessSfdcContacts, onErrorSfdc);});

forcetkClient オブジェクトは、OAuth 2.0 との初期のやりとりの中で設定され、認証されたユーザのコンテキストで Force.com REST API へのアクセス権が付与されます。ここで DE 組織の全取引先責任者の名前を取得します。次に、onSuccessSfdcContacts() によって、index.html ページ上に取引先責任者がリストとして表示されます。$j('#link_fetch_sfdc_accounts').click(function() {

logToConsole("link_fetch_sfdc_accounts clicked");forcetkClient.query("SELECT Name FROM Account",

onSuccessSfdcAccounts, onErrorSfdc);});

#link_fetch_sfdc_contactsハンドラと同様に、#link_fetch_sfdc_accountsハンドラは Force.com REST

API によって取引先レコードを取得します。#link_reset と #link_logoutハンドラによって、表示されたリストのクリアとユーザのログアウトがそれぞれ実行されます。

173

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

このアプリケーションでは、デバイスからも取引先責任者を取得できます。これは同等の Web アプリケーションではできない操作です。次のクリックハンドラは、Cordova の取引責任者プラグインをコールすることにより、デバイスの取引責任者クエリを取得します。$j('#link_fetch_device_contacts').click(function() {

logToConsole("link_fetch_device_contacts clicked");var contactOptionsType = cordova.require(

"org.apache.cordova.contacts.ContactFindOptions");var options = new contactOptionsType();options.filter = ""; // empty search string returns all contactsoptions.multiple = true;var fields = ["name"];var contactsObj = cordova.require(

"org.apache.cordova.contacts.contacts");contactsObj.find(fields, onSuccessDevice,

onErrorDevice, options);});

});

このハンドラで org.apache.cordova.contacts.contacts オブジェクトに対して find() をコールし、デバイスから取引先責任者リストを取得します。onSuccessDevice() 関数 (ここには示されていません) によって、取引先責任者リストが index.html ページに表示されます。完全な ContactExplorer サンプルアプリケーションは、https://github.com/forcedotcom/SalesforceMobileSDK-Shared/tree/master/samples/contactexplorer から入手できます。

関連トピック:

iOS でハイブリッドアプリケーションを実行するAndroid でハイブリッドアプリケーションを作成および実行する

情報をリストするモバイルページを作成するContactExplorer サンプルハイブリッドアプリケーションはさまざまな点で役に立ち、ハイブリッドモバイルアプリケーション開発を学習するときの出発点としても適しています。ここでは、Warehouse というカスタムSalesforce

スキーマから Merchandise レコードを表示するようにこのアプリケーションを変更します。このアプリケーションを Developer Edition 組織にインストールする必要があります。既存の DE 組織にインストールする場合、作成した既存の Warehouse コンポーネントをすべて削除してからインストールしてください。

Warehouse アプリケーションをインストールする1. インストール URL リンク http://goo.gl/1FYg90 をクリックします。2. ログインしている場合は、DE 組織のユーザ名とパスワードを入力します。3. 組織に適した表示レベルを選択します。4. [インストール] をクリックします。5. [完了] をクリックします。6. インストールが完了したら、右上のアプリケーションピッカーから [Warehouse (倉庫)]アプリケーションを

選択できます。

174

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

7. データを作成するには、[データ] タブをクリックします。8. [データを作成] ボタンをクリックします。

メモ:

• Xcode で Cordova iOS プロジェクトを変更する場合、変更のテストのために Staging/www/ プロジェクトフォルダへのコードのコピーが必要になることがあります。Xcode ではなく Cordova コマンドラインのみを使用して Cordova iOS アプリケーションを作成する場合、<projectname>/www/フォルダのみを変更する必要があります。

アプリケーションの初期化ブロックを変更する (index.html)

このセクションでは、アプリケーションを Warehouse スキーマ固有にし、Merchandise カスタムオブジェクトのすべてのレコードを表示するように、ビューファイル (index.html) とコントローラ (inline.js) を変更します。アプリケーションでは、モバイルアプリケーションのデフォルトのホームページに Merchandise レコードのリストが表示されるようにします。そのため、最初に行うのは、アプリケーションが onDeviceReady関数をコールしたときの自動処理の変更です。regLinkClickHanders() への 2 つのコール (onDeviceReady() 関数内と salesforceSessionRefreshed()関数内) をコメントアウトします。続いて、次のコードを index.html

の salesforceSessionRefreshed() 関数の最後に追加します。// log messagelogToConsole("Calling out for records");// register click event handlers -- see inline.js// regLinkClickHandlers();

// retrieve Merchandise records, including the Id for linksforcetkClient.query("SELECT Id, Name, Price__c, Quantity__c

FROM Merchandise__c", onSuccessSfdcMerchandise, onErrorSfdc);

175

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

この JavaScript コードは ForceTK ライブラリを利用して、基本的な SOQL ステートメントで Force.com データベースをクエリし、Merchandise カスタムオブジェクトからレコードを取得します。成功すると、この関数は JavaScript

関数の onSuccessSfdcMerchandise (この後で作成) をコールします。

アプリケーションの mainpage ビューを作成する (index.html)

標準的なモバイルのタッチ指向ユーザインターフェースに Merchandise レコードを表示するには、index.html

をスクロールダウンして、<body> タグの内容全体を次の HTML で置き換えます。<!-- Main page, to display list of Merchandise once app starts --><div data-role="page" data-theme="b" id="mainpage">

<!-- page header --><div data-role="header">

<!-- button for logging out --><a href='#' id="link_logout" data-role="button"

data-icon='delete'>Log Out

</a><!-- page title --><h2>List</h2>

</div><!-- page content --><div id="#content" data-role="content">

<!-- page title --><h2>Mobile Inventory</h2><!-- list of merchandise, links to detail pages --><div id="div_merchandise_list"><!-- built dynamically by function onSuccessSfdcMerchandise --></div>

</div></div>

全体的に見ると、更新されたビューでは、標準 HTML タグと jQuery Mobile マークアップ (data-role、data-theme、data-icon など) を使用してアプリケーションに効果的なタッチインターフェース形式が設定されています。HTML、CSS、JavaScript、jQuery など、基本的な標準 Web 開発技術を習得していれば、ハイブリッドベースのモバイルアプリケーションを開発するのは簡単です。

アプリケーションのコントローラを変更する (inline.js)

前のセクションでは、コントローラの onSuccessSfdcMerchandise 関数に応じて、ビューの初期化ブロックが div_merchandise_list div タグの範囲内で Merchandise リスト項目を表示する HTML を動的に生成しました。このステップでは、onSuccessSfdcMerchandise 関数を作成します。inline.js ファイルを開き、サンプル関数に似た次のコントローラアクションを追加します。

重要: このコードやバイナリファイルのコードを切り取って貼り付ける場合は注意が必要です。コードをプレーンテキストエディタに貼り付け、そこからコピーすることにより、まず純粋なテキストにすることをお勧めします。また、コードステートメントの途中にある改行はすべて削除します。

// handle successful retrieval of Merchandise recordsfunction onSuccessSfdcMerchandise(response) {

// avoid jQuery conflicts

176

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

var $j = jQuery.noConflict();var logToConsole =cordova.require("com.salesforce.util.logger".logToConsole;

// debug info to consolelogToConsole("onSuccessSfdcMerchandise: received " +

response.totalSize + " merchandise records");

// clear div_merchandise_list HTML$j("#div_merchandise_list").html("");

// set the ul string var to a new ULvar ul = $j('<ul data-role="listview" data-inset="true"

data-theme="a" data-dividertheme="a"></ul>');

// update div_merchandise_list with the UL$j("#div_merchandise_list").append(ul);

// set the first li to display the number of records found// formatted using list-dividerul.append($j('<li data-role="list-divider">Merchandise records: '

+ response.totalSize + '</li>'));

// add an li for the merchandise being passed into the function// create array to store record information for click listenerinventory = new Array();// loop through each record, using vars i and merchandise$j.each(response.records, function(i, merchandise) {

// create an array element for each merchandise recordinventory[merchandise.Id] = merchandise;// create a new li with the record's Namevar newLi = $j("<li class='detailLink' data-id='" +

merchandise.Id + "'><a href='#'>" +merchandise.Name + "</a></li>");

ul.append(newLi);});

// render (create) the list of Merchandise records$j("#div_merchandise_list").trigger( "create" );// send the rendered HTML to the log for debugginglogToConsole($j("#div_merchandise_list").html());

// set up listeners for detailLink clicks$j(".detailLink").click(function() {

// get the unique data-id of the record just clickedvar id = $j(this).attr('data-id');// using the id, get the record from the array created abovevar record = inventory[id];

// use this info to set up various detail page information$j("#name").html(record.Name);$j("#quantity").val(record.Quantity__c);$j("#price").val(record.Price__c);$j("#detailpage").attr("data-id",record.Id);

177

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

// change the view to the detailpage$j.mobile.changePage('#detailpage', {changeHash: true});

});

}

コードのコメントで各行について説明されています。この JavaScript に記述された logToConsole();へのコールにより、コンソールログに HTML が表示されたため、コードの作成結果を確認できます。次にサンプル出力の抜粋を示します。<ul data-role="listview" data-inset="true" data-theme="a"

data-dividertheme="a" class="ui-listview ui-listview-insetui-corner-all ui-shadow">

<li data-role="list-divider" role="heading"class=

"ui-li ui-li-divider ui-btn ui-bar-a ui-corner-top">Merchandise records: 6

</li><li class="detailLink ui-btn ui-btn-up-a ui-btn-icon-right ui-li"

data-id="a00E0000003BzSfIAK" data-theme="a"><div class="ui-btn-inner ui-li"><div class="ui-btn-text"><a href="#" class="ui-link-inherit">Tablet</a>

</div></div>

</li><li class="detailLink ui-btn ui-btn-up-a ui-btn-icon-right ui-li"

data-id="a00E0000003BuUpIAK" data-theme="a"><div class="ui-btn-inner ui-li"><div class="ui-btn-text"><a href="#" class="ui-link-inherit">Laptop</a>

</div></div>

</li>

...

</ul>

特に、コードの次の動作に注意します。• アプリケーションの主ページに表示する Merchandise レコードのリストを作成する• Merchandise レコードの名前を表示するための各リスト項目を作成する• 対象の詳細ページに表示される内容を決定する固有のリンク情報を含む各リスト項目を作成する

新規アプリケーションをテストするモバイルアプリケーションのシミュレータを再起動します。起動後、初期ページには次のような画面が表示されます。

178

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

特定の Merchandise レコードをクリックしても、現時点では何も起こりません。リスト機能は便利ですが、詳細ビューと組み合わせることで利便性が向上します。次のセクションでは、ユーザが特定の Merchandise レコードをクリックすると表示される detailpage の作成方法について学習します。

詳細情報のモバイルページを作成する前のトピックでは、起動後にすべての Merchandise レコードを一覧表示し、詳細ページへのリンクを提供するようにサンプルハイブリッドアプリケーションを変更しました。このトピックでは、detailpageビューを作成し、アプリケーションのコントローラを更新して作業を終了します。

アプリケーションの detailpage ビューを作成する (index.html)

ユーザがアプリケーションのmainpageビューで Merchandise レコードをクリックすると、クリックリスナーがレコード固有の情報を生成して、その情報を表示するdetailpageというビューを読み込みます。detailpageビューを作成するには、次の div タグを mainpage div タグの後に追加します。<!-- Detail page, to display details when user clicks specific Merchandise record -->

<div data-role="page" data-theme="b" id="detailpage"><!-- page header -->

179

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

<div data-role="header"><!-- button for going back to mainpage --><a href='#mainpage' id="backInventory"

class='ui-btn-left' data-icon='home'>Home

</a><!-- page title --><h1>Edit</h1>

</div><!-- page content --><div id="#content" data-role="content">

<h2 id="name"></h2><label for="price" class="ui-hidden-accessible">

Price ($):</label><input type="text" id="price" readonly="readonly"></input><br/><label for="quantity" class="ui-hidden-accessible">

Quantity:</label><!-- note that number is not universally supported --><input type="number" id="quantity"></input><br/><a href="#" data-role="button" id="updateButton"

data-theme="b">Update</a></div>

</div>

コメントで、HTML の各部分について説明されています。基本的にこのビューはフォームであり、ユーザはこのビューを使用して Merchandise レコードの [Price (価格)] 項目と [Quantity (数量)] 項目を表示し、必要に応じてレコードの数量を更新できます。onSuccessSfdcMerchandise関数 (inline.js内) の最後の部分で jQuery がコールされ、詳細ページ要素を対象の Merchandise レコードの値で更新します。必要に応じてそのコードを確認します。

アプリケーションのコントローラを変更する (inline.js)

ユーザが新しい detailpage ビューで [Update (更新)] ボタンをクリックするとどうなるでしょうか。現時点では何も起きません。そのボタンのクリックを処理するには、アプリケーションのコントローラ (inline.js) を変更する必要があります。inline.js で、次の JavaScript を onSuccessSfdcMerchandise 関数の最後に追加します。// handle clicks to Update on detailpage$j("#updateButton").click(function() {

// update local information in the inventory arrayinventory[$j("#detailpage").attr("data-id")].Quantity__c = $j("#quantity").val();currentRecord = inventory[$j("#detailpage").attr("data-id")];

// strip out ID before updating the databasevar data = new Object();data.Quantity__c = $j("#quantity").val();// update the databaseforcetkClient.update("Merchandise__c", currentRecord.Id,

data,updateSuccess,onErrorSfdc);});

180

ContactExplorer ハイブリッドサンプルの実行HTML5 およびハイブリッド開発

コードのコメントで各行について説明されています。成功すると、新しいハンドラが updateSuccess 関数(現時点は有効ではない) をコールします。次の簡単な関数を inline.js に追加します。function updateSuccess(message) {

alert("Item Updated");}

アプリケーションをテストするモバイルアプリケーションのシミュレータを再起動します。再起動後、特定の Merchandise レコードをクリックすると、次の画面のような詳細ページが表示されます。

自由にレコードの数量を更新してから、DE 組織にログインし、Force.com アプリケーション UI を使用してレコードを表示したときに同じ数量が表示されることを確認します (上記を参照)。

モバイルデバイスでのハイブリッドアプリケーションのデバッグ

ハイブリッドアプリケーションは、モバイルデバイスで実行されている間にデバッグできます。デバッグの方法は、開発プラットフォームによって異なります。実際のデバイスでアプリケーションが実行された場合にのみ発生するバグに遭遇した場合、デスクトップ開発者ツールを使用してそれらの問題をトラブルシューティングします。場合によっては、開発者が 2 つのランタイムに接続する方法がわからなかったり、その方法が詳細に記載されたドキュメントが見つからなかったりします。次に、マシンの Web アプリケーションデバッガを、接続デバイスで実行されているアプリケーションに接続するためのプラットフォーム固有の一般的な手順を示します。

Android デバイスのハイブリッドアプリケーションのデバッグAndroid デバイスでハイブリッドアプリケーションをデバッグするには、Google Chrome を使用します。次の手順は、https://developer.chrome.com/devtools/docs/remote-debugging に投稿されている完全な手順をまとめたものです。

181

モバイルデバイスでのハイブリッドアプリケーションのデバッグ

HTML5 およびハイブリッド開発

1. https://developer.chrome.com/devtools/docs/remote-debugging の説明に従って、デバイスの USB デバッグを有効にします。

2. デスクトップ (開発) マシンで Chrome を開き、chrome://inspect に移動します。3. [Discover USB Devices (USB デバイスを見つける)] を選択します。4. デバイスを選択します。5. デバイスを使用して、開発マシンで実行されている Web アプリケーションをデバッグする手順は、次のと

おりです。a. [Port forwarding... (ポート転送...)] をクリックします。b. デバイスのポートおよび localhost ポートを設定します。c. [Enable port forwarding (ポート転送を有効にする)] を選択します。詳細は、

https://developer.chrome.com/devtools/docs/remote-debugging#port-forwarding を参照してください。

iOS デバイスで実行されているハイブリッドアプリケーションのデバッグiOS デバイスの実機またはシミュレータでハイブリッドアプリケーションをデバッグするには、デスクトップおよびデバイスで Safari を使用します。1. デスクトップで Safari を開きます。2. [Safari] > [環境設定] を選択します。3. [詳細] タブをクリックします。4. [メニューバーに “開発” メニューを表示] をクリックします。5. iOS シミュレータを使用している場合、次の操作を実行します。

• Xcode が開いている場合、Ctrl キーを押しながら、タスクバーの Xcode アイコンをクリックし、[Open

Developer Tool (開発者ツールを開く)] > [iOS Simulator (iOS シミュレータ)] を選択します。• または、ターミナルウィンドウで、「open -a iOS\ Simulator」と入力します。

6. [iOS Simulator (iOS シミュレータ)] のメニューで、[Hardware (ハードウェア)] > [Device (デバイス)] を選択します。

7. デバイスを選択します。8. デバイスまたは iOS シミュレータのホーム画面から Safari を開きます。9. Web アプリケーションの場所に移動します。10. デスクトップの Safari で、[開発者] > [<あなたのデバイス>] を選択し、デバイスまたはシミュレータの Safari

で開いた URL を選択します。[Web Inspector] ウィンドウが開き、デバイスで実行されている Safari インスタンスに接続されます。

iOS で PhoneGap (Cordova) ハイブリッドアプリケーションをデバッグする手順は、ここを参照してください。https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/を参照してください。

182

iOS デバイスで実行されているハイブリッドアプリケーションのデバッグ

HTML5 およびハイブリッド開発

iOS 7 ハイブリッドアプリケーションでのステータスバーの制御

iOS 7 では、ステータスバーを表示するか非表示にするかと、ステータスバーを Web ビューにオーバーレイ表示するかどうかを選択できます。Cordova ステータスバープラグインを使用してこれらの設定を指定できます。Salesforce Mobile SDK 2.3 以降では、デフォルトでステータスバーが表示され、Web ビューにオーバーレイ表示されます。ステータスバーを非表示にするには、次のキーをアプリケーションの plist に追加します。<key>UIStatusBarHidden</key><true/><key>UIViewControllerBasedStatusBarAppearance</key><false/>

非表示のステータスバーの例については、AccountEditor サンプルアプリケーションを参照してください。ステータスバーの外観 (オーバーレイ、背景色、透過性など) を制御するには、次のように org.apache.cordova.statusbar

をアプリケーションに追加します。cordova plugin add org.apache.cordova.statusbar

外観の制御は、config.xml ファイルまたは JavaScript から行います。完全な手順は、https://github.com/apache/cordova-plugin-statusbarを参照してください。Web ビューにオーバーレイ表示しないステータスバーの例については、ContactExplorer サンプルアプリケーションを参照してください。

関連トピック:

ハイブリッドサンプルアプリケーション

ハイブリッドアプリケーションの JavaScript ファイル

外部連動関係Mobile SDK では、ハイブリッドアプリケーションのさまざまな機能に次の外部連動関係を使用します。

説明外部 JavaScript ファイル

一般的な HTML ユーティリティライブラリjquery.js

SmartSync サポートunderscore.js

SmartSync サポートbackbone.js

含める JavaScript ファイルMobile SDK 2.3 以降では、Cordova ユーティリティがアプリケーションに必要な Cordova プラグインファイルをプロジェクトのプラットフォームディレクトリにコピーします。ユーザがこれらのファイルを www/ フォルダにコピーする必要はありません。

183

iOS 7 ハイブリッドアプリケーションでのステータスバーの制御

HTML5 およびハイブリッド開発

HTML コードに (<script> タグを使用して) 含めるファイルはハイブリッドプロジェクトの種別によって異なります。次に示す各種別について、リストのファイルをすべて含めます。基本的なハイブリッドアプリケーションの場合:

• cordova.js

基本的なハイブリッドアプリケーションから REST API コールを行う場合:

• cordova.js

• forcetk.mobilesdk.js

ハイブリッドアプリケーションで SmartSync を使用する場合:

• jquery.js

• underscore.js

• backbone.js

• cordova.js

• forcetk.mobilesdk.js

• smartsync.js

バージョン設定および JavaScript ライブラリの互換性

ハイブリッドアプリケーションでは、クライアント JavaScript コードは、Cordova (旧 PhoneGap) および SalesforceSDK

プラグインを介してネイティブコードとやりとりします。JavaScript コードをモバイルアプリケーションとパッケージ化する場合は、テストによってコードがネイティブコードと動作することを確認します。ただし、アプリケーションが VisualForce で記述されている場合など、JavaScript コードがサーバから取得される場合は、有害な競合が発生する可能性があります。このような場合は、使用している Mobile SDK とバージョンが適合するCordova の JavaScript ライブラリを使用するように十分注意する必要があります。たとえば、PhoneGap 1.2 を使用するMobile SDK 1.2 を含むアプリケーションを配信し、後からMobile SDK 1.3 を使用する更新を配信するとします。バージョン 1.3 の Mobile SDK では、PhoneGap 1.2 ではなく Cordova 1.8.1 が使用されます。そのため、更新されたアプリケーションの JavaScript コードは、ネイティブコンポーネントへのアクセスに、Cordova 1.8.1 および Mobile SDK 1.3 バージョンの JavaScript ライブラリのみを使用する必要があります。バージョンが適合しない JavaScript ライブラリを使用すると、アプリケーションがクラッシュする可能性があります。クライアントのアップグレードを顧客に強制することはできませんが、ではどのようにしてクラッシュを回避できるでしょうか。まず、クライアントのバージョンを識別します。次に、クライアントが古い場合にはアプリケーションへのアクセスを拒否する (「最新バージョンに更新してください」警告を表示するなど) か、互換性のある JavaScript ライブラリを提供することをお勧めします。次の表に、Cordova および PhoneGap のバージョンと Mobile SDK バージョンの相関付けを示します。

Cordova または PhoneGap のバージョンMobile SDK のバージョン

PhoneGap 1.21.2

Cordova 1.8.11.3

Cordova 2.21.4

184

バージョン設定および JavaScript ライブラリの互換性HTML5 およびハイブリッド開発

Cordova または PhoneGap のバージョンMobile SDK のバージョン

Cordova 2.31.5

Cordova 2.32.0

Cordova 2.32.1

Cordova 2.32.2

Cordova 3.52.3

Cordova 3.63.0

Cordova 3.63.1

Cordova 3.63.2

Cordova 3.63.3

Cordova 5.0.0 (Android)、3.9.2 (iOS)4.0

Cordova 5.0.0 (Android)、3.9.2 (iOS)4.1

Cordova 5.0.0 (Android)、3.9.2 (iOS)4.2

Cordova 5.0.0 (Android)、4.2.0 (iOS)4.3

ユーザエージェントを使用した Mobile SDK のバージョンの検索Mobile SDKのバージョンを検出するには、ユーザエージェント文字列を活用できます。ユーザエージェントは、SalesforceMobileSDK/<version>で開始します。ユーザエージェントを取得したら、返された文字列を解析して Mobile SDK のバージョンを検出できます。ユーザエージェントは、サーバで次の Apex コードを使用して取得できます。userAgent = ApexPages.currentPage().getHeaders().get('User-Agent');

同様に、クライアントでは navigator オブジェクトを使用して JavaScript で取得できます。userAgent = navigator.userAgent;

sdkinfo プラグインを使用した Mobile SDK のバージョンの検出JavaScript では、sdkinfo プラグインを使用して、Mobile SDK のバージョンとその他の情報を取得することもできます。cordova.force.jsファイルで定義されるこのプラグインには、次のメソッドが備えられています。getInfo(callback)

このメソッドは、次の情報を提供する連想配列を返します。

185

バージョン設定および JavaScript ライブラリの互換性HTML5 およびハイブリッド開発

説明メンバー名

コンテナの作成に使用されるSalesforce Mobile SDKのバージョン (「1.4」など)。

sdkVersion

ハイブリッドアプリケーションの名前。appName

ハイブリッドアプリケーションのバージョン。appVersion

コンテナにインストールされたSalesforceプラグインの名前を含む配列 (「com.salesforce.oauth」、「com.salesforce.smartstore」など)。

forcePluginsAvailable

次のコードは、sdkinfo プラグインに保存された情報を取得して、アラートボックスに表示します。var sdkinfo = cordova.require("com.salesforce.plugin.sdkinfo");sdkinfo.getInfo(new function(info) {

alert("sdkVersion->" + info.sdkVersion);alert("appName->" + info.appName);alert("appVersion->" + info.appVersion);alert("forcePluginsAvailable->" +

JSON.stringify(info.forcePluginsAvailable));});

関連トピック:

例: 適切な JavaScript ライブラリの提供

ハイブリッドアプリケーションでのセッション管理

モバイルアプリケーションに影響を与える可能性がある一般的な問題を解決するために、Mobile SDK ではハイブリッドアプリケーションにネイティブコンテナを使用しています。これらのコンテナは、Web セッション管理の複雑さを取り除くことによって、シームレスな認証とセッション管理を提供します。ただし、よく使用されるモバイルアプリケーションアーキテクチャの進化に伴い、「One Size Fits All (1 つのサイズですべてに対応)」というアプローチは制限が厳しすぎることがわかっています。たとえば、モバイルアプリケーションでJavaScript

Remoting in Visualforce を使用していると、セッションが期限切れになった場合に Salesforce Cookie が失われることがあります。この Cookie は、ユーザが手動で再度ログインした場合にのみ取得されます。Mobile SDK では、リアクティブなセッション管理を使用します。ハイブリッドコンテナでセッションを自動的に管理するのではなく、セッションイベントに応答することによって開発者が管理に関与できるようになりました。この戦略により、開発者は、Salesforce Touch プラットフォームでセッション管理をさらに細かく制御できます。Mobile SDK 1.3 以前で開発されたアプリケーションを更新する場合、セッション管理コードをアップグレードする必要があります。リアクティブ管理に切り替えるには、アプリケーションのアーキテクチャに応じてセッション管理の設定を調整します。次の表には、一般的なアーキテクチャの動作と推奨されるアプローチがまとめられています。

186

ハイブリッドアプリケーションでのセッション管理HTML5 およびハイブリッド開発

コードのアップグレード手順

SDK 1.4 以降のリアクティブな動作

SDK 1.3 以前のプロアクティブな動作

アプリケーションアーキテクチャ

forcetk.mobilesdk.js は変更されません。他のフレーム

JavaScript からの更新バックグラウンドセッションの更新

REST API

ワークについては、更新コードを追加します。

タイムアウトをキャッチし、ページの再読み込み

JavaScript からのセッションと CSRF トークンの更新

アプリケーションの再起動

JavaScript Remoting inVisualforce

または新しい iFrame の読み込みを行います。

タイムアウトをキャッチし、ページの再読み込みを行います。

ページの再読み込みアプリケーションの再起動

jQuery Mobile

次のセクションでは、各アーキテクチャの詳しいコーディング手順を示します。

REST API (Apex2REST を含む)REST API を活用するハイブリッドアプリケーションは、各 REST コールの前に期限切れのセッションを検出し、新しいアクセストークンを要求する必要があります。開発者は、forcetk.mobilesdk.js などの API ラップ用ライブラリを活用してセッションの保有期間を管理してください。アプリケーションは、Salesforce リソースへのアクセスを試行する前に、Salesforce OAuth プラグイン上でgetAuthCredentials() をコールする必要があります。getAuthCredentials() に渡すカスタム更新関数(次の例では salesforceSessionRefreshed) とエラー関数を定義します。認証が成功すると、OAuth プラグインは、更新関数をコールし、セッションおよび更新トークンを渡します。アプリケーションは、これらのトークンを使用して forcetk.mobilesdk を初期化します。ContactExplorer サンプルアプリケーションにあるindex.html の次のコードは、ハイブリッドローカルアプリケーションでこのプロトコルを実装する方法を示しています。• アプリケーションは、onDeviceReady() 関数内で getAuthCredentials() をコールします。

cordova.require("com.salesforce.plugin.oauth").getAuthCredentials(salesforceSessionRefreshed,

getAuthCredentialsError);

• 認証が成功すると、OAuth プラグインは salesforceSessionRefreshed() 関数をコールします。// Global authenticated forcetk client instancevar forcetkClient;//...

function salesforceSessionRefreshed(creds) {cordova.require("com.salesforce.util.logger").

logToConsole("salesforceSessionRefreshed");

187

ハイブリッドアプリケーションでのセッション管理HTML5 およびハイブリッド開発

// Depending on how we come into this method, "creds" may// be callback data from the auth plugin, or an event fired// from the plugin.// The data is different between the two.var credsData = creds;// Event sets the "data" object with the auth data.if (creds.data)

credsData = creds.data;forcetkClient = new forcetk.Client(credsData.clientId,

credsData.loginUrl, null,cordova.require("com.salesforce.plugin.oauth").

forcetkRefresh);forcetkClient.setSessionToken(credsData.accessToken,

apiVersion, credsData.instanceUrl);forcetkClient.setRefreshToken(credsData.refreshToken);forcetkClient.setUserAgentString(credsData.userAgent);

}

完全な ContactExplorer サンプルアプリケーションは、https://github.com/forcedotcom/SalesforceMobileSDK-Shared/tree/master/samples/contactexplorer から入手できます。

JavaScript Remoting in VisualforceJavaScript Remotingを使用してVisualforceページにアクセスするモバイルアプリケーションでは、セッションの更新コードをメソッドのパラメータリストに組み込みます。JavaScript で、Visualforceリモートコールを使用して、セッション状態を調べ、適宜調整します。<Controller>.<Method>(

<params>,function(result, event) {

if (hasSessionExpired(event)) {// Reload will try to redirect to login page// Container will intercept the redirect and// refresh the session before reloading the// origin pagewindow.location.reload();

} else {// Everything is OK.// Go ahead and use the result.// ...

},{escape: true}

);

この例では、hasSessionExpired() を次のように定義します。function hasSessionExpired(event) {

return (event.type == "exception" &&event.message.indexOf("Logged in?") != -1);

}

高度な使用事例: ページ全体を再読み込みしても、最適なユーザ操作性が提供されない場合があります。ページ全体の再読み込みを回避するには、次の操作が必要です。

188

ハイブリッドアプリケーションでのセッション管理HTML5 およびハイブリッド開発

1. アクセストークンを更新します。2. Visualforce ドメインの Cookie を更新します。3. 最後に、CSRF トークンを更新します。次のようなページの完全な再読み込みは行いません。window.location.reload();

代わりに、次のようにします。// Refresh oauth tokencordova.require("com.salesforce.plugin.oauth").authenticate(

function(creds) {// Reload hidden iframe that points to a blank page to// to refresh Visualforce domain cookiesvar iframe = document.getElementById("blankIframeId");iframe.src = src;

// Refresh CSRF cookie// Get the provider arrayvar providers = Visualforce.remoting.Manager.providers;// Get the last provider in the arrays (usually only one)var provider = Visualforce.remoting.last;provider.refresh(function() {

//Retry call for a seamless user experience});

},function(error) {

console.log("Refresh failed");}

);

jQuery MobileJQueryMobile では、Ajax コールを行って、ページを表示するためのデータを転送します。セッションが期限切れになると、フレームワークにより 302 エラーがマスクされます。エラーを回復するには、次のコードを組み込んで、ページを強制的に更新します。$(document).on('pageloadfailed', function(e, data) {console.log('page load failed');if (data.xhr.status == 0) {// reloading the VF page to initiate authenticationwindow.location.reload();

}});

189

ハイブリッドアプリケーションでのセッション管理HTML5 およびハイブリッド開発

ログインの延期

Mobile SDKハイブリッドアプリケーションでは、起動時に常にSalesforceログイン画面が表示されます。ただし、これらのアプリケーションは認証を後の時点まで延期することで利点を得られる場合があります。簡単な設定で、アプリケーションの任意の論理的場所まログインを延期できます。遅延ログインの実装は 2 ステップからなるプロセスです。1. 起動時の認証をスキップするようにプロジェクトを設定します。2. JavaScript コードで、認証を開始する時点で forcetk authenticateUser() 関数をコールします。

ステップ 1: 認証をスキップするようにプロジェクトを設定する1. プラットフォーム固有のプロジェクトで、www/bootconfig.json ファイルを開きます。2. shouldAuthenticate プロパティを「false」に設定します。

ステップ 2: JavaScript で認証を開始する認証プロセスを開始するには、(www/js/app.js から) 次の JavaScript 関数をコールします。function authenticateUser(success, fail)

この関数は、成功コールバック関数と失敗コールバック関数の 2 つの引数を取ります。認証に失敗すると、失敗コールバックが呼び出されます。認証に成功すると、次のキーを含む forcetk.Client 引数と共に成功コールバックが呼び出されます。• clientId

• loginUrl

• proxyUrl

• authzHeader

• accessToken (または sessionToken)

• refreshToken

• sessionId

• apiVersion

• instanceUrl

• asyncAjax

• userAgentString

• authCallback

190

ログインの延期HTML5 およびハイブリッド開発

Android ハイブリッドアプリケーションからの SmartStore とSmartSync の削除

forcedroid 3.0 以降を使用してハイブリッド Android アプリケーションを作成すると、SmartStoreおよび SmartSyncモジュールが自動的に含まれます。アプリケーションでこれらのモジュールを使用しない場合は、簡単に削除できます。1. XML エディタでプロジェクトの AndroidManifest.xml を開き、<application> ノードを見つけます。2. android:name 属性を次のように変更します。

android:name="com.salesforce.androidsdk.app.HybridApp"

3. Android Studio で、プロジェクトツールウィンドウを開きます。4. アプリケーションモジュールを選択して [F4]キーを押し、[Module Settings (モジュール設定)] ウィンドウを開

きます。5. [Dependencies (依存関係)] タブで、[:libs:SmartSync] のエントリを Ctrl キーを押しながらクリックするか、右ク

リックして [Remove (削除)] を選択します。6. [Add (追加)] ボタン ([+]) をクリックし、「SalesforceSDK」を選択して [OK] をクリックします。

メモ: 必要に応じて、モジュールの build.gradle ファイルで次の変更を手動で行うことができます。置換前のパスは、次のとおりです。:libs:SmartSync

置換後のパスは、次のとおりです。:libs:SalesforceSDK

7. (省略可能) プロジェクトツールウィンドウで SmartStoreおよび SmartSyncライブラリを選択し、右クリックして [Delete (削除)] をクリックします。

以上の手順で、SmartStore および SmartSync ライブラリの参照が削除され、アプリケーションの基本アプリケーションクラスが HybridAppWithSmartSync Mobile SDK クラスから汎用 HybridApp クラスに変更されます。

例: 適切な JavaScript ライブラリの提供

正しいバージョンの JavaScript ライブラリを提供するには、使用する Salesforce Mobile SDK のバージョンごとに別個のバンドルを作成します。次に、必要なバージョンをダウンロードするサーバに Apex コードを提供します。1. アプリケーションでサポートする Salesforce Mobile SDK のバージョンごとに、次の操作を実行します。

a. 目的の SDK バージョンの JavaScript ライブラリを含む ZIP ファイルを作成します。b. ZIP ファイルを静的リソースとして組織にアップロードします。たとえば、Salesforce Mobile SDK バージョン 1.3 を使用するクライアントを配信する場合は、次のファイルをzip ファイルに追加します。• cordova.force.js

191

Android ハイブリッドアプリケーションからの SmartStoreと SmartSync の削除

HTML5 およびハイブリッド開発

• SalesforceOAuthPlugin.js

• bootconfig.js

• cordova-1.8.1.js (名前を cordova.js に変更する必要があります)

メモ: バンドルでは、Cordova JavaScript ライブラリの名前を cordova.js (PhoneGap-x.x.js ライブラリを使用するバージョンをパッケージ化する場合は PhoneGap.js) に変更できます。

2. 使用するバンドルを判別する Apex コントローラを作成します。コントローラコードで、ユーザエージェント文字列を解析して、クライアントで使用しているバージョンを見つけます。a. 組織の [設定] から、[開発] > [Apex クラス] をクリックします。b. 次の定義を使用して、SDKLibController という名前の新しい Apex コントローラを作成します。

public class SDKLibController {public String getSDKLib() {String userAgent =ApexPages.currentPage().getHeaders().get('User-Agent');

if (userAgent.contains('SalesforceMobileSDK/1.3')) {return 'sdklib13';

}// Add if statements for other SalesforceSDK versions// for which you provide library bundles.

}}

3. バンドル内のライブラリごとに Visualforce ページを作成し、そのページを使用してクライアントを目的のライブラリにリダイレクトします。たとえば、SalesforceOAuthPlugin ライブラリの場合は、次のようになります。a. 組織で、[設定] から、[クイック検索] ボックスに「Visualforce ページ」と入力し、[Visualforce ペー

ジ] を選択します。b. 次の定義を使用して、「SalesforceOAuthPlugin」という名前の新しいページを作成します。

<apex:page controller="SDKLibController"action="{!URLFor($Resource[SDKLib],'SalesforceOAuthPlugin.js')}"></apex:page>

c. HTML コードの <script> タグで VisualForce ページを参照します。必ずステップ 3b で作成したページを指し示すようにしてください。次に例を示します。<script type="text/javascript"src="/apex/SalesforceOAuthPlugin" />

メモ: バンドル内のライブラリごとに別個の <script> タグを指定します。

192

例: 適切な JavaScript ライブラリの提供HTML5 およびハイブリッド開発

第 10 章 オフライン管理

Salesforce Mobile SDKには、データをオフラインで使用するために保存および同期できる、次の 2 つのモジュールがあります。

トピック:

• SmartStore を使用したオフラインデータの安全な保存

• SmartStore では、デバイス上の暗号化されたデータベース、またはスープにアプリケーションデータを保存できます。デバイスが再度オンラインになったときに、SmartStore API を使用してデータの変更を Salesforce サーバと同期できます。• SmartSync を使用し

た Salesforce オブ • SmartSyncは、Salesforceデータを簡単に取得して JavaScript オブジェクトとしてモデル化し、オフラインで使用するためにキャッシュするメカニズムを提供するデージェクトへのアク

セス タフレームワークです。オフラインでの変更をSalesforceサーバにアップロードするときに、SmartSyncを使用して同期プロセスを詳細に制御できます。SmartSyncは一般的な Backbone.jsオープンソースライブラリで構築されており、デフォルトのキャッシュとして SmartStore を使用します。

193

SmartStore を使用したオフラインデータの安全な保存

モバイルデバイスの接続はいつでも失われる可能性があり、病院や飛行機などの環境では接続が禁止されることがよくあります。このような状況に対処するには、モバイルアプリケーションがオフラインになっても引き続き動作するようにすることが重要です。Mobile SDK は、モバイルデバイス向けの安全なマルチスレッドオフラインストレージソリューションであるSmartStore を備えています。SmartStore により、ユーザはデバイスの接続が失われても安全な環境で作業を続行できます。

Mobile SDK 4.3 の SmartStore の新機能• Android のみ、SmartStore の SQLCipher がバージョン 3.5.2 (2016 年 7 月) にアップグレードされています。iOS の

場合、SmartStore の SQLCipher は 3.4.0 (2016 年 4 月) のままです。• 特定の極端な状況でパフォーマンスを向上させるため、外部ストレージの非常に大きいスープ要素を逐次

化するオプションがSmartStoreに追加されました。「大きいスープ要素での外部ストレージの使用」を参照してください。

このセクションの内容:

SmartStore についてSmartStoreでは、オフラインストレージのキャッシュと共に、非リレーショナルデスクトップデータベースの主要な機能 (データセグメント化、インデックス付け、クエリ) を使用できます。ハイブリッドおよびネイティブアプリケーションでの SmartStore の有効化ハイブリッド Android アプリケーションで SmartStore を使用するには、いくつかの追加ステップを実行します。既存の Android アプリケーションへの SmartStore の追加Mobile SDK 4.0 以降で作成されたハイブリッドプロジェクトには、自動的に SmartStore が含まれます。Mobile

SDK 4.0 以降を使用して SmartStore なしの Android ネイティブプロジェクトを作成した場合でも、後で簡単にSmartStore を追加できます。スープの登録スープにアクセスするには、まずスープを登録する必要があります。インデックスパスでの配列の使用インデックスパスに配列を含めることができますが、特定のルールが適用されます。スープの入力オフラインアクセス用に Salesforce レコードをスープに追加するには、REST API と SmartStore API を組み合わせて使用します。スープからのデータの取得SmartStore には、クエリ文字列を作成する一連のヘルパーメソッドが備えられています。スマート SQL クエリクエリを完全に制御したり、既存の SQL クエリを再利用したりするには、カスタム SmartStoreクエリを定義します。

194

SmartStore を使用したオフラインデータの安全な保存オフライン管理

全文検索クエリの使用SmartStoreで効率的かつ柔軟な検索を実行するには、全文クエリを使用します。全文クエリは「like」クエリと比べて、大きいデータセットを処理する場合にパフォーマンス上の大きな利点があります。クエリ結果の処理Mobile SDKには、各プラットフォームで効率的、柔軟かつ動的にクエリ結果にアクセスできるメカニズムがあります。データの挿入、更新、および更新/挿入SmartStore では、エントリを追跡して外部サーバとスープを同期できる標準項目が定義されます。大きいスープ要素での外部ストレージの使用スープに大きい要素が含まれている場合、暗号化された外部ストレージを使用してパフォーマンスを改善できます。トレードオフは最小限です。スープ要素の削除従来より、SmartStoreのメソッドでは要素 ID の配列を指定してスープ要素を削除できます。通常これを行うには、候補 ID を取得する事前クエリを実行してから、削除を実行するメソッドをコールします。Mobile SDK

4.2 では SmartStore が強化され、要素削除メソッドにクエリオプションが追加されました。このオプションではクエリのみを指定し、SmartStore はそのクエリに適合するすべての要素を削除します。この方法では 1

回のコールでクエリと削除操作の両方が行われるため、パフォーマンスが向上します。スープの管理SmartStoreには、スープメタデータを取得して、スープレベルの他の操作を実行できるユーティリティ機能が用意されています。この機能は、ハイブリッド、Android ネイティブ、および iOS ネイティブアプリケーションで使用できます。グローバル SmartStore の使用通常はSmartStoreインスタンスを特定の顧客のログイン情報に関連付けますが、特別な要件でグローバルインスタンスにアクセスすることもできます。SmartStore インスペクタを使用したテストテスト中に SmartStore の操作を確認することは面倒で時間がかかります。SmartStore インスペクタでこの問題を解消できます。擬似 SmartStore の使用コンテナ外で実行しながらSmartStoreを使用するコードの開発とテストを容易にするため、エミュレートされた SmartStore を使用できます。

SmartStore についてSmartStore では、オフラインストレージのキャッシュと共に、非リレーショナルデスクトップデータベースの主要な機能 (データセグメント化、インデックス付け、クエリ) を使用できます。オフライン同期および競合の解決サービスを提供するため、SmartStore は StoreCache (Mobile SDK のキャッシュメカニズム) を使用します。StoreCache を使用して、Salesforce データの操作を管理することをお勧めします。

メモ: 純粋な HTML5 アプリケーションは、オフライン情報をブラウザのキャッシュに保存します。ブラウザのキャッシュはMobile SDKの一部ではないため、ここでは説明していません。SmartStoreは、ストレージ機能をデバイスで使用します。この方法には、ネイティブ開発またはハイブリッド開発が必要です。

195

SmartStore についてオフライン管理

サンプルコードについてこの章のコードスニペットでは、すべてのSalesforce組織で事前定義されている取引先オブジェクトと商談オブジェクトを使用しています。取引先と商談は主従関係でリンクされています。1 つの取引先が複数の商談のマスタになる場合があります。

このセクションの内容:

SmartStore のスープSmartStore のスープでは、オフラインコンテンツをパーティションで区切ることができます。SmartStore のデータ型他のデータベース同様、SmartStoreではスープの作成に使用する一連のデータ型が定義されます。SmartStore

のデータ型は、基礎となる SQLite データベースと同じです。

関連トピック:

オフラインキャッシュのための StoreCache の使用競合検出スマート SQL クエリ

SmartStore のスープSmartStore のスープでは、オフラインコンテンツをパーティションで区切ることができます。SmartStore は、スープと呼ばれる論理コレクションにオフラインデータを保存します。SmartStore スープは、基盤となる SQLite データベースの 1 つのテーブルを表し、通常は標準またはカスタム Salesforce オブジェクトに対応付けられます。スープにはスープ要素が含まれます。各要素は、1 つのデータベース行を反映する JSON オブジェクトです。データアクセスを合理化するには、各スープのインデックスを定義します。SmartStoreヘルパーメソッドまたは SmartStore の Smart SQL クエリ言語でこれらのインデックスを使用してスープをクエリします。SmartStore はまた、全文検索クエリをサポートするため、管理業務が容易になります。スープはアプリケーションにいくつでも保存できますが、自己完結型のデータセットで、スープ間にリレーションはありません。

警告: SmartStoreデータは揮発性です。この有効期限は、認証されたユーザおよび OAuth トークンの状態に関係します。顧客がアプリケーションからログアウトすると、SmartStore がそのユーザに関連付けられているすべてのスープデータを削除します。同様に、OAuth 更新トークンが取り消されるか、期限切れになると、顧客のアプリケーションの状態がリセットされ、SmartStore のすべてのデータが消去されます。アプリケーションを設計するときは、特に組織で更新トークンの有効期限を短期に設定する場合に、SmartStore

データの揮発性に留意します。

SmartStore のデータ型他のデータベース同様、SmartStore ではスープの作成に使用する一連のデータ型が定義されます。SmartStore のデータ型は、基礎となる SQLite データベースと同じです。SmartStore では、「インデックス指定」を宣言するために次のデータ型がサポートされます。SmartStore のスープ定義では、インデックス指定は SmartStore が特定の項目内で検索するデータ型を定義します。

196

SmartStore についてオフライン管理

説明型

4 バイト (SDK 2.1 以前) または 8 バイト (SDK 2.2 以降) で保存される符号付き整数

integer

8 バイトの IEEE 浮動小数点数として保存される浮動小数点値

floating

データベースエンコード (UTF-8) で保存されるテキスト文字列

string

全文検索をサポートする文字列full_text

SQLite JSON1 拡張に基づくインデックスの型。integer、floating、string 型の代わりに使用できます。JSON1 では

JSON1

配列をトラバースするインデックスパスがサポートされないこと以外は、各型のインデックス指定と同様に動作します。

このセクションの内容:

日付表現

関連トピック:

インデックスパスでの配列の使用

日付表現SmartStoreでは、日付/時間データ型は定義されません。日付/時間項目のインデックス指定を作成する場合は、JSON 入力の形式に一致する SmartStore の型を選択します。たとえば、Salesforce は日付を文字列として送信するため、Salesforceの日付項目には常に文字列インデックス指定を使用します。Salesforce以外の日付項目やカスタム日付項目のインデックスの型を選択する場合は、次の表を参照してください。

説明形式型

「YYYY-MM-DD HH:MM:SS.SSS」ISO 8601 文字列string

グリニッジの紀元前 4714 年 11 月 24

日の正午からの予期的グレゴリオユリウス日数floating

暦に応じた日数。この値には、小数で表される部分的な日数を含めることができます。

1970-01-01 00:00:00 UTC からの秒数Unix 時間integer

197

SmartStore についてオフライン管理

ハイブリッドおよびネイティブアプリケーションでの SmartStore の有効化ハイブリッド Android アプリケーションで SmartStoreを使用するには、いくつかの追加ステップを実行します。ハイブリッドアプリケーションでは、JavaScript を使用して SmartStore にアクセスします。ハイブリッドアプリケーションでオフラインアクセスを有効にするには、Visualforceまたは HTML ページに cordova.jsライブラリファイルを含める必要があります。forcedroid ネイティブアプリケーションでは、SmartStore は省略可能なコンポーネントで、明示的に含める必要があります。• 対話形式で forcedroid create を使用してネイティブ Android プロジェクトを作成する場合、SmartStore

を使用するかどうか確認を求められたら、「yes」を指定します。• コマンドラインパラメータが含まれる forcedroid create を使用する場合、省略可能な

––usesmartstore=yes パラメータを指定します。iOS アプリケーションでは、SmartStore は常に含まれます。forceios create を使用して iOS プロジェクトを作成する場合は、この機能が暗黙的に含まれるため、SmartStore を使用するオプションが表示されません。

関連トピック:

Android プロジェクトの作成forceios を使用した iOS プロジェクトの作成

既存の Android アプリケーションへの SmartStore の追加Mobile SDK 4.0 以降で作成されたハイブリッドプロジェクトには、自動的に SmartStore が含まれます。Mobile SDK

4.0 以降を使用してSmartStoreなしの Android ネイティブプロジェクトを作成した場合でも、後で簡単に SmartStore

を追加できます。既存のネイティブ Android プロジェクト (Mobile SDK 4.0 以降) に SmartStore を追加する手順は、次のとおりです。1. SmartStore ライブラリプロジェクトをプロジェクトに追加します。Android Studio で、プロジェクトの

build.gradle ファイルを開き、dependencies セクションで :libs:SmartStore の compile ディレクティブを追加します。dependencies セクションが存在しない場合は作成します。dependencies {...compile project(':libs:SmartStore')

}

2. <projectname>App.java ファイルで、SalesforceSDKManager の代わりに SmartStoreSDKManager

クラスをインポートします。次のステートメントを置換します。import com.salesforce.androidsdk.

app.SalesforceSDKManager

置換後のステートメントは、次のとおりです。import com.salesforce.androidsdk.smartstore.app.SmartStoreSDKManager

198

ハイブリッドおよびネイティブアプリケーションでのSmartStore の有効化

オフライン管理

3. <projectname>App.java ファイルで、SalesforceSDKManager ではなく SmartStoreSDKManager クラスを拡張するようにアプリケーションクラスを変更します。

メモ: Mobile SDK 3.x 以前で作成したアプリケーションに SmartStoreを追加するには、最初に最新バージョンの Mobile SDK にアップグレードします。

関連トピック:

以前のリリースからの移行

スープの登録スープにアクセスするには、まずスープを登録する必要があります。スープを登録するには、スープ名および 1 つ以上のインデックス指定のリストを指定します。次のハイブリッド、Android、および iOS の各例では、名前、ID、および所有者 (または親) ID 項目で構成されるインデックス指定配列を作成します。そのエントリで検出された 1 つ以上の項目にスープをインデックス付けします。SmartStoreにより、これらのインデックスが挿入、更新、削除操作を反映していることが確認されます。スープを登録する場合、少なくとも1 つのインデックス項目を常に指定します。たとえば、シンプルなキー/値ストアとしてスープを使用している場合は、文字列型の 1 つのインデックス指定を使用します。

メモ: スープに非常に大きい要素 (1 MB 以上) が含まれている場合、外部ストレージを使用するように登録することを検討してください。「大きいスープ要素での外部ストレージの使用」を参照してください。

ハイブリッドアプリケーションスープを登録する JavaScript 関数には、正常およびエラー条件用のコールバック関数が必要です。navigator.smartstore.registerSoup(soupName, indexSpecs, successCallback, errorCallback)

スープが存在しない場合は、この関数で作成されます。スープが存在する場合は、登録することでスープにアクセスできます。indexSpecs

indexSpecs 配列を使用して、事前定義されたインデックス付けでスープを作成します。 indexSpecs 配列のエントリは、スープのインデックス付け方法を指定します。各エントリは、path:typeペアで構成されます。path はインデックス項目の名前、type は「string」、「integer」、「floating」、「full_text」、または「json1」のいずれかです。"indexSpecs":[

{"path":"Name","type":"string"

}{

"path":"Id","type":"string"

}{

199

スープの登録オフライン管理

"path":"ParentId","type":"string"

}]

メモ:

• インデックスパスでは大文字と小文字が区別され、Owner.Nameなどの複合パスを含めることができます。

• indexSpecs配列で記述された項目が不足しているインデックスエントリは、そのインデックスで追跡されなくなります。

• インデックスのタイプは、インデックスにのみ適用されます。インデックス付き項目 (「select

{soup:path} from {soup}」など) をクエリすると、インデックス指定で指定したタイプのデータが返されます。

• インデックス列には null 項目を含めることができます。• Mobile SDK 4.1 以降、「内部」(非リーフ) ノードへのインデックスパスを指定できます。これらのパ

スを likeおよび match (全文) クエリで使用できます。内部ノードパスを定義する場合は、string

型を使用します。たとえば、「spies」という名前のスープに次の要素があるとします。{

"first_name":"James","last_name":"Bond","address":{

"street_number":10,"street_name":"downing","city":"london"

}}

この場合、「address」には子があるため、これは内部ノードです。「address」パスのインデックスを介して、likeまたは matchクエリを使用して「address」内の「city」で値「london」を検索できます。たとえば、次のように使用します。SELECT {spies:first_name, spies:last_name} FROM spies WHERE {spies:address} LIKE'london'

• Mobile SDK 4.1 以降、インデックスパスに配列を含めることができますが、いくつかの制限があります。「インデックスパスでの配列の使用」を参照してください。

successCallback

指定した成功コールバック関数は、1 つの引数 (スープ名) を取ります。次に例を示します。function(soupName) { alert("Soup " + soupName + " was successfully created"); };

スープが正常に作成されると、registerSoup()は、成功コールバック関数をコールして、スープの準備が整ったことを示します。トランザクションが完了するまで待機し、他の操作を開始する前にコールバックを受け取ります。渡された名前でスープを登録すると、成功コールバック関数からスープが返されます。

200

スープの登録オフライン管理

errorCallback

エラーコールバック関数は、1 つの引数 (エラーの説明文字列) を取ります。function(err) { alert ("registerSoup failed with error:" + err); }

スープの作成時にエラーが発生する場合、次のようなさまざまな理由が考えられます。• スープ名が無効または不正である• インデックスがない (少なくとも 1 つのインデックス指定が必要)

• データベースエラーなど、他の予期しないエラーが発生したスープが存在するかどうかを確認するには、次の関数を使用します。navigator.smartstore.soupExists(soupName, successCallback, errorCallback);

Android ネイティブアプリケーションAndroid の場合、com.salesforce.androidsdk.smartstore.store.IndexSpec タイプの配列でインデックス指定を定義します。各インデックス指定はパス (インデックス項目名) と型で構成されます。インデックス指定の型は SmartStore.Type Enum で定義され、次の値が含まれます。• string

• integer

• floating

• full_text

• json1

SmartStoreSDKManager sdkManager =SmartStoreSDKManager.getInstance();

SmartStore smartStore = sdkManager.getSmartStore();

IndexSpec[] ACCOUNTS_INDEX_SPEC = {new IndexSpec("Name", Type.string),new IndexSpec("Id", Type.string),new IndexSpec("OwnerId", Type.string)};

smartStore.registerSoup("Account", ACCOUNTS_INDEX_SPEC);

iOS ネイティブアプリケーションiOS の場合、SFSoupIndexオブジェクトの配列でインデックス指定を定義します。各インデックス指定はパス(インデックス項目名) と型で構成されます。インデックス指定の型は、SFSoupIndex クラスで定数として定義され、次の値があります。• kSoupIndexTypeString

• kSoupIndexTypeInteger

• kSoupIndexTypeFloating

• kSoupIndexTypeFullText

201

スープの登録オフライン管理

• kSoupIndexTypeJSON1

NSString* const kAccountSoupName = @"Account";

...

- (SFSmartStore *)store{

return [SFSmartStore sharedStoreWithName:kDefaultSmartStoreName];}

...

- (void)createAccountsSoup {if (![self.store soupExists:kAccountSoupName]) {

NSArray *keys = @[@"path", @"type"];NSArray *nameValues = @[@"Name", kSoupIndexTypeString];NSDictionary *nameDictionary = [NSDictionary

dictionaryWithObjects:nameValues forKeys:keys];

NSArray *idValues = @[@"Id", kSoupIndexTypeString];NSDictionary *idDictionary =

[NSDictionary dictionaryWithObjects:idValues forKeys:keys];

NSArray *ownerIdValues = @[@"OwnerId", kSoupIndexTypeString];NSDictionary *ownerIdDictionary =

[NSDictionary dictionaryWithObjects:ownerIdValuesforKeys:keys];

NSArray *accountIndexSpecs =[SFSoupIndex asArraySoupIndexes:@[nameDictionary,

idDictionary, ownerIdDictionary]];

NSError* error = nil;[self.store registerSoup:kAccountSoupName

withIndexSpecs:accountIndexSpecserror:&error];

if (error) {NSLog(@"Cannot create SmartStore soup '%@'\nError: '%@'",

kAccountSoupName, error.localizedDescription);}

}}

関連トピック:

SmartStore のデータ型全文検索クエリの使用

インデックスパスでの配列の使用インデックスパスに配列を含めることができますが、特定のルールが適用されます。

202

インデックスパスでの配列の使用オフライン管理

Mobile SDK 4.1 より前は、インデックスパスでは対応付け (辞書または連想配列) のみがサポートされていました。たとえば、a.b.c などのパスの場合、SmartStoreでは b と c 両方の対応付けが必要でした。これらの対応付けがない場合にパスを評価すると、SmartStore は何も返しませんでした。Mobile SDK 4.1 以降では、インデックスパスに配列と対応付けを含めることができます。a.b.c の例では、b の値が配列の場合、SmartStore では c を定義する対応付けが含まれる配列が求められます。その後、SmartStore はb 配列の対応付けで見つかった c キーの値が含まれる配列を返します。

メモ: JSON1 インデックス指定で配列をトラバースするインデックスパスは使用できません。

例: 次の表に、a.b.c パスのさまざまな例と SmartStore クエリによって返される値を示します。

パス a.b.c の値スープ要素の例説明

1{

"a":{

配列なし

"b":{ "c":1 }}

}

[1,

{"a":{

c は配列 (内部ノード) を示します。

2,"b":{3

]"c":[1,2,3]

}}

}

[1,

{"a":{

bは対応付けの配列を示します。一部の対応付けには cキーが含まれます。その他の対応付けは無視されます。

2]

"b":[{

"c":1},{

"c":2},{

"no-c":3}

]}

}

[0,

{"a":[

aは対応付けの配列を示します。一部の対応付けには、bがキーを含む対応付けを示すものがありま [

1,{

"b":{す。bが対応付けの配列を示すも2"c":0

203

インデックスパスでの配列の使用オフライン管理

パス a.b.c の値スープ要素の例説明

}},

のもあります。cキーの値のみが返されます。

]]

{"b":[

{"c":1

},{

"c":2},{

"no-c":3}

]}

]}

スープの入力オフラインアクセス用に Salesforce レコードをスープに追加するには、REST API と SmartStore API を組み合わせて使用します。スープを登録する場合、データを待機しているメモリ内に空の名前付き構造を作成します。通常、Salesforce組織のデータを使用してスープを初期化します。Salesforce データを取得するには、Mobile SDK の標準 REST 要求メカニズムを使用します。REST の成功応答が返されたら、応答オブジェクトのデータを抽出して、スープに更新/挿入します。

ハイブリッドアプリケーションハイブリッドアプリケーションは、forcetk.mobilesdk.js ライブラリで定義された SmartStore 関数を使用します。この例では、[Fetch Contacts (取引先責任者の取得)] ボタンのクリックハンドラがforcetkClient.query()をコールし、単純な SOQL クエリ ("SELECT Name, Id FROM Contact") を Salesforce

に送信します。このコールにより、REST 応答を受信するコールバック関数としてonSuccessSfdcContacts(response) が指定されます。onSuccessSfdcContacts(response) 関数は、responseで返されたレコードを反復処理し、UI コントロールにSalesforce値を入力します。最後に、応答のすべてのレコードをサンプルスープに更新/挿入します。// Click handler for the “fetch contacts” button$('#link_fetch_sfdc_contacts').click(function() {

logToConsole()("link_fetch_sfdc_contacts clicked");forcetkClient.query("SELECT Name,Id FROM Contact",

onSuccessSfdcContacts, onErrorSfdc);});

204

スープの入力オフライン管理

function onSuccessSfdcContacts(response) {logToConsole()("onSuccessSfdcContacts: received " +

response.totalSize + “ contacts");var entries = [];

$("#div_sfdc_contact_list").html("");var ul = $('<ul data-role="listview" data-inset="true"

data-theme="a" data-dividertheme="a"></ul>');$("#div_sfdc_contact_list").append(ul);

ul.append($('<li data-role="list-divider">Salesforce Contacts: ' +

response.totalSize + '</li>'));$.each(response.records, function(i, contact) {

entries.push(contact);logToConsole()("name: " + contact.Name);var newLi = $("<li><a href='#'>" + (i+1) + " - " +

contact.Name + "</a></li>");ul.append(newLi);

});

if (entries.length > 0) {sfSmartstore().upsertSoupEntries(SAMPLE_SOUP_NAME,

entries,function(items) {

var statusTxt = "upserted: " + items.length +" contacts";

logToConsole()(statusTxt);$("#div_soup_status_line").html(statusTxt);$("#div_sfdc_contact_list").trigger( "create" );

},onErrorUpsert);

}}

function onErrorUpsert(param) {logToConsole()("onErrorUpsert: " + param);$("#div_soup_status_line").html("Soup upsert ERROR");

}

iOS ネイティブアプリケーションiOS ネイティブアプリケーションは、REST API のやりとりに SFRestAPI プロトコルを使用します。次のコードは、SOQL クエリ SELECT Name, Id, OwnerId FROM Account の REST 要求を作成して送信します。要求に成功すると、Salesforceは REST 応答を requestForQuery:send:delegate: 代理メソッドに送信します。応答が解析され、返された各レコードが SmartStore スープに更新/挿入されます。- (void)requestAccounts{

SFRestRequest *request = [[SFRestAPI sharedInstance]requestForQuery:@"SELECT Name, Id, OwnerId FROM Account"];

[[SFRestAPI sharedInstance] send:request delegate:self];}

205

スープの入力オフライン管理

//SFRestAPI protocol for successful response- (void)request:(SFRestRequest *)request didLoadResponse:(id)dataResponse{

NSArray *records = dataResponse[@"records"];if (nil != records) {

for (int i = 0; i < records.count; i++) {[self.store upsertEntries:@[records[i]]

toSoup:kAccountSoupName];}

}}

Android ネイティブアプリケーション通常、Android ネイティブアプリケーションは、RestClient.sendAsync()メソッドと AsyncRequestCallback

インターフェースの匿名インライン定義を組み合わせて使用し、REST API のやりとりを行います。次のコードは、SOQL クエリ SELECT Name, Id, OwnerId FROM Account の REST 要求を作成して送信します。要求に成功すると、Salesforceは REST 応答を指定の AsyncRequestCallback.onSuccess()コールバックメソッドに送信します。応答が解析され、返された各レコードが SmartStore スープに更新/挿入されます。private void sendRequest(String soql, final String obj)throws UnsupportedEncodingException {

final RestRequest restRequest =RestRequest.getRequestForQuery(

getString(R.string.api_version),"SELECT Name, Id, OwnerId FROM Account", "Account");

client.sendAsync(restRequest, new AsyncRequestCallback() {@Overridepublic void onSuccess(RestRequest request,

RestResponse result) {try {

final JSONArray records =result.asJSONObject().getJSONArray("records");

insertAccounts(records);} catch (Exception e) {

onError(e);} finally {

Toast.makeText(MainActivity.this,"Records ready for offline access.",Toast.LENGTH_SHORT).show();

}}

}});

}

/*** Inserts accounts into the accounts soup.** @param accounts Accounts.*/public void insertAccounts(JSONArray accounts) {

206

スープの入力オフライン管理

try {if (accounts != null) {

for (int i = 0; i < accounts.length(); i++) {if (accounts[i] != null) {

try {smartStore.upsert(

ACCOUNTS_SOUP, accounts[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.");

}}

スープからのデータの取得SmartStore には、クエリ文字列を作成する一連のヘルパーメソッドが備えられています。スープからデータを取得するため、SmartStore ではクエリ指定を作成するヘルパー関数を使用できます。クエリ指定はインデックス指定と似ていますが、クエリのタイプとそのパラメータに関するより多くの情報が含まれています。クエリビルダーメソッドは、次のクエリを実行できる指定を生成します。• すべて (「all」クエリ)

• Smart SQL の使用• キーの完全一致 (「exact」クエリ)

• 特定のパスでの全文検索 (「match」クエリ)

• 値の範囲 (「range」クエリ)

• ワイルドカード一致 (「like」クエリ)

レコードセットをクエリするには、指定に適したクエリ指定ファクトリメソッドをコールします。必要に応じて、次の表に示すインデックス項目、並び替え順、および絞り込みに使用する他のメタデータも定義できます。

説明パラメータ

(JavaScript では省略可能) 指定した項目のリストのみにクエリ範囲を絞り込みます。「項目のサブセットを返すクエリの絞り込み」を参照してください。

selectPaths またはwithSelectPaths

名前、取引先番号、日付などの検索対象を説明します。indexPath または path

(JavaScript では省略可能) クエリ範囲の開始を定義するために使用されます。beginKey

207

スープからのデータの取得オフライン管理

説明パラメータ

(JavaScript では省略可能) クエリ範囲の終了を定義するために使用されます。endKey

(JavaScript では省略可能) exact または match クエリの検索文字列を指定するために使用されます。

matchKey

(JavaScript では省略可能。デフォルトで path パラメータの値が設定されます)

exact、range、および like クエリで、結果セットの並び替えに使用されるインデッorderPath

クス付きパス項目を指定します。並べ替えなしでクエリするには、このパラメータを null 値に設定します。

メモ: Mobile SDK バージョン 3.2 以前では、クエリで指定されたインデックス付きパス項目のすべてのクエリが並び替えられます。

(JavaScript では省略可能)order

• JavaScript: 「ascending」(デフォルト) または「descending」のいずれかです。• iOS: kSFSoupQuerySortOrderAscending または

kSFSoupQuerySortOrderDescending のいずれかです。• Android: Order.ascending または Order.descending のいずれかです。

(JavaScript では省略可能。指定されていない場合、ネイティブプラグインによって、結果の Cursor.pageSize の最適値が計算されます) 結果の各ページに返すレコード数。

pageSize

たとえば、次の buildRangeQuerySpec() JavaScript コールについて考えます。navigator.smartstore.buildRangeQuerySpec(

"name", "Aardvark", "Zoroastrian", "ascending", 10, "name");

このコールは、Aardvark と Zoroastrian の間の名前が含まれるエントリを検索し、name 項目を昇順で並び替えるrange クエリ指定を作成します。{

"querySpec":{"queryType":"range","indexPath":"name","beginKey":"Aardvark","endKey":"Zoroastrian","orderPath":"name","order":"ascending","pageSize":10

}}

JavaScript build* 関数では、関数コールの最後でのみ省略可能なパラメータを省略できます。1 つ以上のパラメータをスキップしてから、スキップする各オプションのダミー値または null 値を入力せずに次のパラメータを指定することはできません。たとえば、次のコールを使用できます。• buildAllQuerySpec(indexPath)

208

スープからのデータの取得オフライン管理

• buildAllQuerySpec(indexPath, order)

• buildAllQuerySpec(indexPath, order, pageSize)

• buildAllQuerySpec(indexPath, order, pageSize, selectPaths)

ただし、次のコールは order パラメータが省略されているため、使用できません。buildAllQuerySpec(indexPath, pageSize)

メモ: すべてのパラメータ化されたクエリは 1 つの述語の検索です。結合をサポートするのはスマートSQL クエリのみです。

すべてのクエリスープ内のすべてをトラバースします。ページサイズについての詳細は、「クエリ結果の処理」を参照してください。

メモ: 基本的には、画面に表示するエントリ数に合わせて pageSizeを設定します。円滑なスクロール表示を行うには、表示するエントリ数の 2 倍または 3 倍に値を増やします。

JavaScript:

buildAllQuerySpec(indexPath, order, pageSize, selectPaths) は、スープ内のすべてのエントリを返します。特定の順序では並び替えられません。order と pageSize は省略可能で、デフォルトはそれぞれ「ascending」と 10 です。selectPaths 引数も省略可能です。iOS ネイティブ:

+ (SFQuerySpec*) newAllQuerySpec:(NSString*)soupNamewithPath:(NSString*)pathwithOrder:(SFSoupQuerySortOrder)order

withPageSize:(NSUInteger)pageSize;

+ (SFQuerySpec*) newAllQuerySpec:(NSString*)soupNamewithSelectPaths:(NSArray*)selectPathswithOrderPath:(NSString*)orderPath

withOrder:(SFSoupQuerySortOrder)orderwithPageSize:(NSUInteger)pageSize;

Android ネイティブ:

public static QuerySpec buildAllQuerySpec(String soupName,String path,Order order,int pageSize)

public static QuerySpec buildAllQuerySpec(String soupName,String[] selectPaths,String orderPath,Order order,int pageSize);

209

スープからのデータの取得オフライン管理

スマート SQL SELECT ステートメントを含むクエリ特定の Smart SQL ステートメントで指定されたクエリを実行します。この関数では独自の SELECT ステートメントを指定するため、他のクエリファクトリ関数に比べて柔軟性が高まります。「スマート SQLクエリ」を参照してください。次のサンプルコードは、SQL COUNT 関数をコールする Smart SQL クエリです。JavaScript:

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});

JavaScript では、pageSize は省略可能で、デフォルトは 10 です。iOS ネイティブ:

SFQuerySpec* querySpec =[SFQuerySpec

newSmartQuerySpec:@"select count(*) from {employees}"withPageSize:1];

NSArray* result = [_store queryWithQuerySpec:querySpec pageIndex:0];// result should be [[ n ]] if there are n employees

Android ネイティブ:

SmartStore store =SmartStoreSDKManager.getInstance().

getSmartStore();JSONArray result =

store.query(QuerySpec.buildSmartQuerySpec("select count(*) from {employees}", 1), 0);

// result should be [[ n ]] if there are n employees

Exact によるクエリindexPath 値の特定の matchKey と完全に一致するエントリを見つけます。特定の ID の子エンティティを検索する場合に、このメソッドを使用します。たとえば、Status 別の商談を検索できます。JavaScript:

JavaScript では、order パラメータを「ascending」または「descending」のいずれかに設定できます。order、pageSize、および orderPathは省略可能で、デフォルトはそれぞれ「ascending」、10、および path引数です。selectPaths 引数も省略可能です。navigator.smartstore.buildExactQuerySpec(

path, matchKey, pageSize, order, orderPath, selectPaths)

次の JavaScript コードは、ID によって子を取得します。var querySpec = navigator.smartstore.buildExactQuerySpec(

“sfdcId”,

210

スープからのデータの取得オフライン管理

“some-sfdc-id”);navigator.smartstore.querySoup(“Catalogs”,

querySpec, function(cursor) {// we expect the catalog to be in:// cursor.currentPageOrderedEntries[0]

});

次の JavaScript コードは、親 ID によって子を取得します。var querySpec = navigator.smartstore.buildExactQuerySpec(“parentSfdcId”, “some-sfdc-id);navigator.smartstore.querySoup(“Catalogs”, querySpec, function(cursor) {});

iOS ネイティブ:

iOS では、order パラメータを kSFSoupQuerySortOrderAscending またはkSFSoupQuerySortOrderDescending のいずれかに設定できます。クエリ範囲を特定の項目に絞り込むには、2 つ目の形式を使用し、withSelectPaths パラメータで項目名の配列を渡します。+ (SFQuerySpec*) newExactQuerySpec:(NSString*)soupName

withPath:(NSString*)pathwithMatchKey:(NSString*)matchKeywithOrderPath:(NSString*)orderPath

withOrder:(SFSoupQuerySortOrder)orderwithPageSize:(NSUInteger)pageSize;

+ (SFQuerySpec*) newExactQuerySpec:(NSString*)soupNamewithSelectPaths:(NSArray*)selectPaths

withPath:(NSString*)pathwithMatchKey:(NSString*)matchKeywithOrderPath:(NSString*)orderPath

withOrder:(SFSoupQuerySortOrder)orderwithPageSize:(NSUInteger)pageSize;

Android ネイティブ:

Android では、order パラメータを Order.ascending または Order.descending のいずれかに設定できます。クエリ範囲を特定の項目に絞り込むには、2 つ目の形式を使用し、selectPaths パラメータで項目名の配列を渡します。public static QuerySpec buildExactQuerySpec(

String soupName, String path, String exactMatchKey,String orderPath, Order order, int pageSize)

public static QuerySpec buildExactQuerySpec(String soupName, String[] selectPaths, String path,String exactMatchKey, String orderPath,Order order, int pageSize);

Match によるクエリindexPath 値の matchKey で全文検索クエリと完全に一致するエントリを見つけます。「全文検索クエリの使用」を参照してください。JavaScript:

211

スープからのデータの取得オフライン管理

JavaScript では、order パラメータを「ascending」または「descending」のいずれかに設定できます。order、pageSize、および orderPathは省略可能で、デフォルトはそれぞれ「ascending」、10、および path引数です。selectPaths 引数も省略可能です。navigator.smartstore.buildMatchQuerySpec(

path, matchKey, order, pageSize, orderPath, selectPaths)

iOS ネイティブ:

iOS では、order パラメータを kSFSoupQuerySortOrderAscending またはkSFSoupQuerySortOrderDescending のいずれかに設定できます。クエリ範囲を特定の項目に絞り込むには、2 つ目の形式を使用し、withSelectPaths パラメータで項目名の配列を渡します。+ (SFQuerySpec*) newMatchQuerySpec:(NSString*)soupName

withPath:(NSString*)pathwithMatchKey:(NSString*)matchKeywithOrderPath:(NSString*)orderPath

withOrder:(SFSoupQuerySortOrder)orderwithPageSize:(NSUInteger)pageSize;

+ (SFQuerySpec*) newMatchQuerySpec:(NSString*)soupNamewithSelectPaths:(NSArray*)selectPaths

withPath:(NSString*)pathwithMatchKey:(NSString*)matchKeywithOrderPath:(NSString*)orderPath

withOrder:(SFSoupQuerySortOrder)orderwithPageSize:(NSUInteger)pageSize;

Android ネイティブ:

Android では、order パラメータを Order.ascending または Order.descending のいずれかに設定できます。クエリ範囲を特定の項目に絞り込むには、2 つ目の形式を使用し、selectPaths パラメータで項目名の配列を渡します。public static QuerySpec buildMatchQuerySpec(

String soupName, String path, String exactMatchKey,String orderPath, Order order, int pageSize)

public static QuerySpec buildMatchQuerySpec(String soupName, String[] selectPaths, String path,String matchKey, String orderPath, Order order,int pageSize)

Range によるクエリindexPath の値が beginKey と endKey で定義された範囲内にあるエントリを見つけます。整数として保存された日付範囲など、数値範囲で検索する場合にこの関数を使用します。beginKey と endKey に null 値を渡すと、範囲無期限の検索を実行できます。• indexPath での項目が beginKey 以上のすべてのレコードを見つけるには、null 値を endKey に渡しま

す。• indexPath での項目が endKey 以下のすべてのレコードを見つけるには、null 値を beginKey に渡しま

す。

212

スープからのデータの取得オフライン管理

• すべてをクエリするには、null 値を beginKey と endKey の両方に渡します。JavaScript:

JavaScript では、order パラメータを「ascending」または「descending」のいずれかに設定できます。order、pageSize、および orderPathは省略可能で、デフォルトはそれぞれ「ascending」、10、および path引数です。selectPaths 引数も省略可能です。navigator.smartstore.buildRangeQuerySpec(

path, beginKey, endKey, order, pageSize, orderPath, selectPaths)

iOS ネイティブ:

iOS では、order パラメータを kSFSoupQuerySortOrderAscending またはkSFSoupQuerySortOrderDescending のいずれかに設定できます。クエリ範囲を特定の項目に絞り込むには、2 つ目の形式を使用し、withSelectPaths パラメータで項目名の配列を渡します。+ (SFQuerySpec*) newRangeQuerySpec:(NSString*)soupName

withPath:(NSString*)pathwithBeginKey:(NSString*)beginKeywithEndKey:(NSString*)endKey

withOrderPath:(NSString*)orderPathwithOrder:(SFSoupQuerySortOrder)order

withPageSize:(NSUInteger)pageSize;

+ (SFQuerySpec*) newRangeQuerySpec:(NSString*)soupNamewithSelectPaths:(NSArray*)selectPaths

withPath:(NSString*)pathwithBeginKey:(NSString*)beginKeywithEndKey:(NSString*)endKey

withOrderPath:(NSString*)orderPathwithOrder:(SFSoupQuerySortOrder)order

withPageSize:(NSUInteger)pageSize;

Android ネイティブ:

Android では、order パラメータを Order.ascending または Order.descending のいずれかに設定できます。クエリ範囲を特定の項目に絞り込むには、2 つ目の形式を使用し、selectPaths パラメータで項目名の配列を渡します。public static QuerySpec buildRangeQuerySpec(

String soupName, String path, String beginKey,String endKey, String orderPath, Order order, int pageSize)

public static QuerySpec buildRangeQuerySpec(String soupName, String[] selectPaths, String path,String beginKey, String endKey, String orderPath,Order order, int pageSize);

Like によるクエリindexPathの値が指定の likeKeyに似ているエントリを見つけます。次の構文例に示すように、部分一致を検索するには「%」ワイルドカードを使用します。• キーワードで開始する用語を検索する場合は「foo%」

213

スープからのデータの取得オフライン管理

• キーワードで終了する用語を検索する場合は「%foo」• indexPath 値のどこかにあるキーワードを検索する場合は「%foo%」一般検索および名前の部分一致を行う場合に、この関数を使用します。全文クエリおよび大きいデータセットでの高速クエリには、「match」によるクエリメソッドを使用します。

メモ: 「like」によるクエリは、クエリメソッドの中で最も低速です。JavaScript:

JavaScript では、order パラメータを「ascending」または「descending」のいずれかに設定できます。order、pageSize、および orderPathは省略可能で、デフォルトはそれぞれ「ascending」、10、および path引数です。selectPaths 引数も省略可能です。navigator.smartstore.buildLikeQuerySpec(

path, likeKey, order, pageSize, orderPath, selectPaths)

iOS ネイティブ:

iOS では、order パラメータを kSFSoupQuerySortOrderAscending またはkSFSoupQuerySortOrderDescending のいずれかに設定できます。クエリ範囲を特定の項目に絞り込むには、2 つ目の形式を使用し、withSelectPaths パラメータで項目名の配列を渡します。+ (SFQuerySpec*) newLikeQuerySpec:(NSString*)soupName

withPath:(NSString*)pathwithLikeKey:(NSString*)likeKey

withOrderPath:(NSString*)orderPathwithOrder:(SFSoupQuerySortOrder)order

withPageSize:(NSUInteger)pageSize;

+ (SFQuerySpec*) newLikeQuerySpec:(NSString*)soupNamewithSelectPaths:(NSArray*)selectPaths

withPath:(NSString*)pathwithLikeKey:(NSString*)likeKey

withOrderPath:(NSString*)orderPathwithOrder:(SFSoupQuerySortOrder)order

withPageSize:(NSUInteger)pageSize;

Android ネイティブ:

Android では、order パラメータを Order.ascending または Order.descending のいずれかに設定できます。クエリ範囲を特定の項目に絞り込むには、2 つ目の形式を使用し、selectPaths パラメータで項目名の配列を渡します。public static QuerySpec buildLikeQuerySpec(

String soupName, String path, String likeKey,String orderPath, Order order, int pageSize)

public static QuerySpec buildLikeQuerySpec(String soupName, String[] selectPaths,String path, String likeKey, String orderPath,Order order, int pageSize)

214

スープからのデータの取得オフライン管理

クエリの実行JavaScript では、クエリは非同期に実行され、成功コールバック関数にカーソルが返されるか、エラーコールバック関数にエラーが返されます。成功コールバックは、function(cursor) の形式を取ります。クエリ指定を querySoup メソッドに渡すには、querySpec パラメータを使用します。navigator.smartstore.querySoup(soupName, querySpec,

successCallback, errorCallback);

項目のサブセットを返すクエリの絞り込みSmart SQLクエリ指定では、Smart SQLステートメントで項目を指定し、クエリが返す項目のリストを制限できます。他のタイプのクエリ指定では、selectPaths パラメータを使用して同じ処理を行うことができます。この引数を使用する場合、メソッドはクエリを満たす各要素の配列を含む配列の配列を返します。各要素配列には、selectPathsで指定された項目のみが含まれます。このパラメータは、「all」、「exact」、「match」、「range」、「like」クエリ指定で使用できます。次に例を示します。次のような要素を含むスープがあるとします。{"_soupEntryId":1, "name":"abc", "status":"active", ...},{"_soupEntryId":2, "name":"abd", "status":"inactive", ...}, ...

LIKE キーとして「ab%」、パスとして name を使用する「like」クエリを実行しましょう。このクエリは、オブジェクトの配列を返します。各オブジェクトには要素全体が含まれます。[ {"_soupEntryId":1, "name": "abc", "status":"active",...},{"_soupEntryId":2, "name":"abd", "status":"inactive",...},...]

次に、選択されたパスとして _soupEntryIdと nameを追加してクエリを絞り込みましょう。このクエリは、より効率的な _soupEntryId および name 項目の値のみが含まれる配列の配列を返します。[[1, "abc"], [2, "abd"], ...]

主キーによる個々のスープエントリの取得すべてのスープエントリには、一意の内部 ID (スープ内のすべてのエントリを保持する内部テーブルにおける主キー) が自動的に与えられます。この ID 項目は、スープエントリで _soupEntryId 項目として使用できます。JavaScript で _soupEntryId によってスープエントリを検索するには、retrieveSoupEntries 関数を使用します。この関数ではスープエントリを最も速く取得できますが、使用できるのは _soupEntryId がわかっている場合のみです。navigator.smartStore.retrieveSoupEntries(soupName, indexSpecs,

successCallback, errorCallback)

返される順序は保証されません。また、削除されたエントリは結果の配列では返されません。

215

スープからのデータの取得オフライン管理

スマート SQL クエリクエリを完全に制御したり、既存の SQL クエリを再利用したりするには、カスタム SmartStore クエリを定義します。Salesforce Mobile SDKバージョン 2.0 以降では、自由形式の SELECT ステートメント用に SmartStoreでスマート SQLクエリ言語がサポートされます。スマート SQLクエリでは、スープおよびスープ項目の参照用に、標準 SQL SELECT

の文法が他の記述子と組み合わされます。これにより、結合の使用を含め、制御および柔軟性が最大限に高まります。スマート SQL では、標準 SQL SELECT 構造がすべてサポートされます。

スマート SQL の制限• スマート SQL でサポートされるのは、SELECT ステートメントおよびインデックス付きパスのみです。• Smart SQL を使用して MATCH クエリを記述することはできません。たとえば、次のクエリは機能しません。

SELECT {soupName:_soup} FROM {soupName} WHERE {soupName:name} MATCH 'cat'

構文構文は標準 SQL SELECT の仕様と同じですが、次の点で違いがあります。

構文使用方法

{<soupName>:<path>}列を指定する{<soupName>}テーブルを指定する{<soupName>:_soup}スープエントリの JSON 文字列全体

を参照する{<soupName>:_soupEntryId}内部スープエントリ ID を参照する{<soupName>:_soupLastModifiedDate}最終更新日を参照する

サンプルクエリEmployees および Departments という名前の 2 つのスープについて考えます。Employees スープには、次の標準項目が含まれています。• 名 (firstName)

• 姓 (lastName)

• 部署コード (deptCode)

• 従業員 ID (employeeId)

• マネージャ ID (managerId)

Departments スープには、次の項目が含まれています。• 名 (name)

• 部署コード (deptCode)

216

スマート SQL クエリオフライン管理

次に、これらのスープを使用した基本的なスマート SQL クエリをいくつか示します。select {employees:firstName}, {employees:lastName}from {employees} order by {employees:lastName}

select {departments:name}from {departments}order by {departments:deptCode}

結合スマート SQL では、ユーザが結合を使用することもできます。次に例を示します。select {departments:name}, {employees:firstName} || ' ' || {employees:lastName}from {employees}, {departments}where {departments:deptCode} = {employees:deptCode}order by {departments:name}, {employees:lastName}

さらに、自己結合を行うこともできます。select mgr.{employees:lastName}, e.{employees:lastName}from {employees} as mgr, {employees} as ewhere mgr.{employees:employeeId} = e.{employees:managerId}

集計関数スマート SQL では、次のような集計関数の使用をサポートしています。• COUNT

• SUM

• AVG

次に例を示します。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}

全文検索クエリの使用SmartStore で効率的かつ柔軟な検索を実行するには、全文クエリを使用します。全文クエリは「like」クエリと比べて、大きいデータセットを処理する場合にパフォーマンス上の大きな利点があります。Mobile SDK 3.3 以降、SmartStoreでは全文検索がサポートされます。全文検索は、インターネット検索エンジンでWeb 上にあるドキュメントを照合するテクノロジです。

217

全文検索クエリの使用オフライン管理

全文検索について全文検索は次のように機能します。まず、顧客が 1 つ以上の用語を入力します。必要に応じて、顧客はバイナリ演算子を使用して用語を結合したり、グループ化して語句にしたりできます。全文検索エンジンが、指定された演算子とグルーピングを適用して該当用語を評価します。検索エンジンが評価後の検索パラメータを使用して一致するドキュメントを検索するか、SmartStore の場合は一致するスープ要素を検索します。全文検索をサポートするため、SmartStore にはスープ項目を定義するための全文インデックス指定、およびスープ項目に対するクエリを実行するためのクエリ指定が備えられています。全文クエリまたは「match」クエリは、「like」クエリよりも効率的です。「like」クエリはすべてのキーの完全なインデックススキャンが必要で、実行時間は検索行数に比例します。「match」クエリは、インデックス内で特定の用語を検索し、関連付けられたレコード ID を返します。全文検索の最適化は、1000 未満のレコードではあまり効果はありませんが、そのしきい値を超えると、レコード数が増加しても実行時間はほぼ一定になります。何万件ものレコードを検索する場合、「match」クエリは「like」クエリよりも 10 ~ 100 倍高速です。全文項目と全文クエリを使用する場合は、次の点に留意してください。• 全文インデックス項目を使用した挿入は、通常の挿入よりも時間がかかります。• Smart SQL ステートメントでは MATCH クエリを実行できません。たとえば、次のクエリはサポートされてい

ません。SELECT {soupName:_soup} FROM {soupName} WHERE {soupName:name} MATCH 'cat'

代わりに、「match」クエリ指定を使用します。

全文検索による最新情報の把握Mobile SDK 4.2 では、SmartStore の全文検索バージョンが FTS4 から FTS5 に更新されます。このアップグレードによって、Mobile SDK は全文インデックス指定を利用できます。アプリケーションを Mobile SDK 4.1 から 4.2 にアップグレードした場合、既存の FTS4 仮想テーブルは変更されません。一方、アップグレード後に作成する新規スープでは FTS5 仮想テーブルが使用されます。これらのスープはすべてシームレスに機能しますが、従来のスープをアップグレードすることもできます。alterSoup をコールし、元のインデックス指定セットに渡すだけです。このコールは、FTS5 を使用して、全文インデックス指定をサポートする仮想テーブルを再作成します。FTS4 と FTS5 の比較については、www.sqlite.org/fts5.html の「Appendix A」を参照してください。

このセクションの内容:

全文検索インデックス指定全文検索を使用するには、1 つ以上の全文インデックス付きパスを使用してスープを登録します。SmartStore

には、インデックス項目を設計するための full_text インデックス指定が備えられています。全文クエリ指定全文クエリを実行するには、プラットフォームの照合クエリメソッドを使用して SmartStore の「match」クエリ指定を作成します。matchKey 引数の場合、全文検索クエリを指定します。全文クエリ構文Mobile SDK の全文クエリは、SQLite の拡張クエリ構文を使用します。この構文では、論理演算子を使用して検索を絞り込むことができます。

218

全文検索クエリの使用オフライン管理

全文検索インデックス指定全文検索を使用するには、1 つ以上の全文インデックス付きパスを使用してスープを登録します。SmartStoreには、インデックス項目を設計するための full_text インデックス指定が備えられています。全文インデックスを含むパスを定義した場合、そのパスを全文以外のクエリに使用することもできます。これらの他のタイプのクエリ (「all」、「exact」、「like」、「range」、「smart」クエリ) は、全文インデックス付き項目を文字列インデックス付き項目として解釈します。次の例に、全文インデックス指定をインスタンス化する方法を示します。

例: iOS:

[[SFSoupIndex alloc]initWithDictionary:@{kSoupIndexPath: @"some_path",kSoupIndexType: kSoupIndexTypeFullText}]

Android:

new IndexSpec("some_path", Type.full_text)

JavaScript:

new navigator.smartstore.SoupIndexSpec("some_path", "full_text")

全文クエリ指定全文クエリを実行するには、プラットフォームの照合クエリメソッドを使用してSmartStoreの「match」クエリ指定を作成します。matchKey 引数の場合、全文検索クエリを指定します。次のメソッドを使用して、全文クエリ指定を作成します。iOS:

+ (SFQuerySpec*) newMatchQuerySpec:(NSString*)soupNamewithPath:(NSString*)path

withMatchKey:(NSString*)matchKeywithOrderPath:(NSString*)orderPath

withOrder:(SFSoupQuerySortOrder)orderwithPageSize:(NSUInteger)pageSize;

+ (SFQuerySpec*) newMatchQuerySpec:(NSString*)soupNamewithSelectPaths:(NSArray*)selectPaths

withPath:(NSString*)pathwithMatchKey:(NSString*)matchKeywithOrderPath:(NSString*)orderPath

withOrder:(SFSoupQuerySortOrder)orderwithPageSize:(NSUInteger)pageSize;

Android:

public static QuerySpec buildMatchQuerySpec(String soupName, String path, String exactMatchKey,String orderPath, Order order, int pageSize)

219

全文検索クエリの使用オフライン管理

public static QuerySpec buildMatchQuerySpec(String soupName, String[] selectPaths, String path,String matchKey, String orderPath, Order order,int pageSize)

JavaScript:

navigator.smartstore.buildMatchQuerySpec(path, matchKey, order, pageSize, orderPath, selectPaths)

全文クエリ構文Mobile SDKの全文クエリは、SQLite の拡張クエリ構文を使用します。この構文では、論理演算子を使用して検索を絞り込むことができます。次の表に、Mobile SDK のクエリでサポートされる構文オプションを示します。表の後に、さまざまなクエリスタイルとサンプル出力の例をキー付きで示します。詳細は、sqlite.orgのセクション 3.1「Full-text Index Queries」および 3.2「Set Operations Using The Enhanced Query Syntax」を参照してください。

関連する例SmartStore の動作クエリオプション

g、h、i、j、k定義したパスにある値のみとの照合を実行します。

1 つ以上の全文インデックス付きパスを指定する

a、b、c、d、e、fすべての全文インデックス付きパスとの照合を実行します。

パスを null 値に設定する

メモ: パスが null の場合でも、matchKey 引数で対象項目を指定できます。{soupName:path}:term形式を使用します。

b、h用語の間に「AND」があるとみなされます。

演算子やグルーピングを使用せずに複数の用語を指定する

d、jクエリ用語で開始する単語が含まれる行が一致します。

用語の末尾にアスタリスクを追加する

c、i一方または両方の用語を検索します。

用語の間に「OR」を使用する

e、f、kその用語が含まれる行を無視します。

用語の前に単項「NOT」演算子を使用する

1 つ以上の全文インデックス付き項目に語句全体が含まれるスープ要素を返します。

複数の用語を二重引用符 (“ ”) で囲んで語句検索を指定する

220

全文検索クエリの使用オフライン管理

例: この例では、「animals」という名前のスープに次のレコードが含まれています。name 項目と color

項目は full_text としてインデックス付けされています。{"id”: 1, "name": "cat", "color": "black"}{"id”: 2, "name": "cat", "color": "white"}{"id”: 3, "name": "dog", "color": "black"}{"id”: 4, "name": "dog", "color": "brown"}{"id”: 5, "name": "dog", "color": "white"}

表 6 : クエリ構文の例返されるレコード

選択レコード一致キーパス例

1、3全文インデックス付き項目に単語「black」が含まれるレコード

“black”nulla.

1全文インデックス付き項目に単語「black」および「cat」が含まれるレコード

“black cat”nullb.

1、2、3全文インデックス付き項目に単語「black」または

“black OR cat”nullc.

「cat」のいずれかが含まれるレコード

1、3全文インデックス付き項目に「b」で始まる単語が含まれるレコード

“b*”nulld.

3全文インデックス付き項目に単語「black」が含まれ、

“black NOT cat”nulle.

単語「cat」は含まれないレコード

3color 項目に単語「black」が含まれ、全文インデックス

“{animals:color}:black NOTcat”

nullf.

付き項目に単語「cat」が含まれないレコード

1、3color項目に単語「black」が含まれるレコード

“black”“color”g.

レコードなしcolor項目に単語「black」および「cat」が含まれるレコード

“black cat”“color”h.

1、3color項目に単語「black」または「cat」のいずれかが含まれるレコード

“black OR cat”“color”i.

221

全文検索クエリの使用オフライン管理

返されるレコード

選択レコード一致キーパス例

1、3color 項目に「b」で始まる単語が含まれるレコード

“b*”“color”j.

1、3color項目に単語「black」が含まれ、単語「cat」は含まれないレコード

“black NOT cat”“color”k.

クエリ結果の処理Mobile SDK には、各プラットフォームで効率的、柔軟かつ動的にクエリ結果にアクセスできるメカニズムがあります。多くの場合、クエリで返される結果セットはメモリにすべて一括で読み込むには大きすぎます。この場合、Mobile SDKは指定されたサイズに基づいて最初に結果の小さいサブセット (1 ページ) を返します。その後その他の結果ページを取得し、結果セットの前後に移動できます。JavaScript:

JavaScript でクエリを実行すると、SmartStore はクエリ結果をページ処理できるカーソルオブジェクトを返します。コードを使用して、カーソルが置かれるページを前後に移動できます。カーソルが置かれるページを移動するには、次の関数を使用します。• navigator.smartstore.moveCursorToPageIndex(cursor, newPageIndex, successCallback,

errorCallback) — カーソルを特定のページインデックスに移動します。0 は最初のページ、totalPages

- 1 は最後のページです。• navigator.smartstore.moveCursorToNextPage(cursor, successCallback, errorCallback) —

次のエントリページに移動します (存在する場合)。• navigator.smartstore.moveCursorToPreviousPage(cursor, successCallback, errorCallback)

— 前のエントリページに移動します (存在する場合)。• navigator.smartstore.closeCursor(cursor, successCallback, errorCallback) — 終了した

ら、カーソルを閉じます。

メモ:

• successCallback 関数には、1 つの引数 (更新後のカーソル) を指定します。• カーソルはデータの静的スナップショットではなく、動的です。カーソルで保持されるデータは、元

のクエリと結果セットでの現在の位置のみです。カーソルを移動すると、クエリが再度実行されます。カーソルのページ移動中にスープを変更すると、カーソルでその変更が表示されます。新しく作成されたスープエントリにアクセスすることもできます (元のクエリの結果が返されている場合)。

iOS ネイティブ:

内部的には、iOS ネイティブアプリケーションはサードパーティの FMResultSet クラスを使用してクエリ結果を取得します。SmartStoreクエリ指定メソッドをコールするときに、pageSizeパラメータを使用して各コールから戻されるデータ量を制御します。結果のページをトラバースするには、同じクエリ指定オブジェクトで

222

クエリ結果の処理オフライン管理

SFSmartStore クラスの queryWithQuerySpec:pageIndex:withDB: またはqueryWithQuerySpec:pageIndex:error:メソッドを開始値 0 の pageIndex引数を増減しながら繰り返しコールします。Android ネイティブ:

内部的には、Android ネイティブアプリケーションはカーソルの操作に android.database.Cursorインターフェースを使用します。SmartStore クエリ指定メソッドをコールするときに、pageSize パラメータを使用して各コールから戻されるデータ量を制御します。結果のページをトラバースするには、同じクエリ指定オブジェクトで SmartStore.query() メソッドを開始値 0 の pageIndex 引数を増減しながら繰り返しコールします。

データの挿入、更新、および更新/挿入SmartStore では、エントリを追跡して外部サーバとスープを同期できる標準項目が定義されます。

システム項目: _soupEntryId and _soupLastModifiedDateスープエントリの挿入、更新、および削除アクションを追跡するために、SmartStore は各エントリに次の項目を追加します。• _soupEntryId — この項目は、特定のスープのテーブルに含まれるスープエントリの主キーです。• _soupLastModifiedDate、_soupCreatedDate — 1/1/1970 からのミリ秒数です。

– 日付値を JavaScript 日付に変換するには、new Date(entry._soupLastModifiedDate)を使用します。– 日付を 1/1/1970 を起点とした対応するミリ秒数に変換するには、date.getTime() を使用します。

スープエントリを挿入または更新すると、これらの項目が SmartStore で自動的に設定されます。特定のエントリを削除または取得するときは、_soupEntryId でそのエントリを参照できます。Mobile SDK 4.2 以降、SmartStore では _soupLastModifiedDate および _soupCreatedDate 項目のインデックスが作成されます。このインデックスにより、これらの項目を使用するクエリのパフォーマンスが向上します。古いスープでは、_soupLastModifiedDateおよび _soupCreatedDate項目は存在しますが、インデックスは作成されません。従来のスープでこれらのインデックスを作成するには、alterSoup をコールし、元のインデックス指定セットを渡すだけです。

更新/挿入についてスープエントリを挿入または更新するには、upsertメソッドを使用します (挿入と更新のどちらのアクションが適切かは SmartStore が判断します)。更新/挿入予定のエントリに _soupEntryId がすでに設定されている場合は、SmartStore がその ID と一致するスープエントリを更新します。更新/挿入エントリに _soupEntryId スロットが存在しないか、指定した_soupEntryId が既存のスープエントリと一致しない場合は、SmartStore がスープにエントリを挿入し、その_soupEntryId を上書きします。

メモ: _soupEntryId または _soupLastModifiedDate の値を直接編集しないでください。

223

データの挿入、更新、および更新/挿入オフライン管理

外部 ID を使用した更新/挿入スープエントリが外部システムのデータを反映している場合、通常は外部の主キー ID を使用してそのエントリを参照します。そのため、外部 ID を使用した更新/挿入が SmartStore でサポートされています。更新/挿入を実行する場合、任意のインデックス項目を外部 ID 項目として指定できます。SmartStore では、指定された項目と同じ値を持つ既存のスープエントリが検索され、次の結果が得られます。• 同じ値を持つ項目が存在しない場合、SmartStore はスープエントリを作成します。• 外部 ID 項目が存在する場合、SmartStore は一致する外部 ID 値を使用してエントリを更新します。• 外部 ID と一致する項目が複数存在すると、SmartStore はエラーを返します。エントリをローカルで作成するには、新しいエントリをサーバにアップロードするときにクエリできる値に、外部 ID 項目を設定します。外部データを使用してスープを更新する場合は、常に外部 ID を使用します。これにより、同じリモートレコードに対してスープエントリが重複しないことが保証されます。SmartStore では、オブジェクト間のリレーションを追跡することもできます。たとえば、サーバにはまだ存在しないカタログに属する商品をオフラインで作成するとします。parentSoupEntryId項目を使用して、商品のカタログエントリとのリレーションを取得できます。サーバにカタログが存在するようになったら、ローカル商品レコードの parentExternalId 項目を更新して外部リレーションを取得できます。

更新/挿入メソッドJavaScript:

cordova.force.js ライブラリには、次の 2 つの JavaScript 更新/挿入関数があります。navigator.smartStore.upsertSoupEntries(isGlobalStore, soupName,

entries[], successCallback, errorCallback)

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

ローカルデータのみを更新/挿入するには、最初の upsert() 関数を使用します。外部サーバからデータを更新/挿入するには、externalPathId パラメータがサポートされる 2 番目の関数を使用します。iOS ネイティブ:

iOS SFSmartStore クラスには、2 つの更新/挿入用インスタンスメソッドがあります。最初のメソッドでは、使用可能なすべてのオプションを指定できます。• スープ名• インデックス指定が含まれる NSArray オブジェクト• 外部 ID 項目名のパス• エラーをアプリケーションに送信する出力 NSError オブジェクト- (NSArray *)upsertEntries:(NSArray *)entries

toSoup:(NSString *)soupNamewithExternalIdPath:(NSString *)externalIdPath

error:(NSError **)error;

224

データの挿入、更新、および更新/挿入オフライン管理

2 番目のメソッドは、外部 ID パスに _soupEntryId 項目を使用します。- (NSArray *)upsertEntries:(NSArray *)entries

toSoup:(NSString *)soupName;

Android ネイティブ:

Android には、upsert()メソッドの 3 つのオーバーロードがあります。最初のオーバーロードでは、使用可能なすべてのオプションを指定できます。• スープ名• 1 つ以上の更新/挿入のエントリが含まれる JSON オブジェクト• 任意の外部 ID 項目名のパス• 挿入と更新にトランザクションモデルを使用するかどうかを示すフラグpublic JSONObject upsert(

String soupName, JSONObject soupElt, String externalIdPath,boolean handleTx)

throws JSONException

2 番目のオーバーロードは、挿入と更新にトランザクションモデルを使用します。

public JSONObject upsert(String soupName, JSONObject soupElt, String externalIdPath)throws JSONException

3 番目のオーバーロードは、トランザクションモデルを適用して外部 ID パスに _soupEntryId 項目を使用します。public JSONObject upsert(

String soupName, JSONObject soupElt)throws JSONException

例: 次の JavaScript コードには、サンプルシナリオが含まれています。まず、upsertSoupEntriesをコールして、取引先のスープエントリを作成します。コールバックに成功したら、新しく割り当てられたスープエントリ ID を持つ新しいレコードを取得します。次に、取引先の説明を変更し、forcetk.mobilesdk

メソッドをコールして、サーバでアカウントを作成し、更新します。最後のコールは、外部 ID を使用した更新/挿入を示します。コードを見やすくするため、エラーコールバックは指定していません。また、SmartStore コールはすべて非同期であるため、実際のアプリケーションでは、前のステップの成功コールバックで各ステップを実行します。このコードでは、レコードがサーバにまだ存在しないため、id項目の値に newを使用しています。アプリケーションがオンラインになったら、ローカルにのみ存在するレコードをクエリ (id == "new" であるレコードを検索) して、それをサーバにアップロードできます。新しいレコードの ID がサーバから返されると、アプリケーションはスープ内のその id 項目を更新できます。// Specify data for the account to be createdvar acc = {id: "new", Name: "Cloud Inc",

Description: "Getting started"};

// Create account in SmartStore// This upsert does a "create" because

225

データの挿入、更新、および更新/挿入オフライン管理

// the account has no _soupEntryId fieldnavigator.smartstore.upsertSoupEntries("accounts", [ acc ],

function(accounts) {acc = accounts[0];// acc should now have a _soupEntryId field// (and a _lastModifiedDate as well)

});

// Update account's description in memoryacc["Description"] = "Just shipped our first app ";

// Update account in SmartStore// This does an "update" because acc has a _soupEntryId fieldnavigator.smartstore.upsertSoupEntries("accounts", [ acc ],

function(accounts) {acc = accounts[0];

});

// Create account on server// (sync client -> server for entities created locally)forcetkClient.create("account", {

"Name": acc["Name"],"Description": acc["Description"]},function(result) {

acc["id"] = result["id"];// Update account in SmartStorenavigator.smartstore.upsertSoupEntries("accounts", [ acc ]);

});

// Update account's description in memoryacc["Description"] = "Now shipping for iOS and Android";

// Update account's description on server// Sync client -> server for entities existing on serverforcetkClient.update("account", acc["id"],

{"Description": acc["Description"]});

// Later, there is an account (with id: someSfdcId) that you want// to get locally

// There might be an older version of that account in the// SmartStore already

// Update account on client// sync server -> client for entities that might or might not// exist on clientforcetkClient.retrieve(

"account", someSfdcId, "id,Name,Description",function(result) {

// Create or update account in SmartStore// (looking for an account with the same sfdcId)navigator.smartstore.upsertSoupEntriesWithExternalId(

"accounts", [result], "id");});

226

データの挿入、更新、および更新/挿入オフライン管理

大きいスープ要素での外部ストレージの使用スープに大きい要素が含まれている場合、暗号化された外部ストレージを使用してパフォーマンスを改善できます。トレードオフは最小限です。スープに入力するときに、SmartStore はデータ要素を JSON 文字列形式に設定し、スープデータを基盤となるSQLite データベースに書き込みます。ほとんどの場合、この方法は効果的で使いやすいことがわかっています。ただし、JSON blob が 1 MB 以上の場合、暗号化されたデバイスファイルシステムに保存するように SmartStore に指示できます。これを行うため、Mobile SDK 4.3 以降には SmartStore 特殊機能である外部ストレージが定義されています。大きい要素に外部ストレージを使用すると、メモリ使用量が軽減されるため、SmartStore のパフォーマンスが向上します。スープ要素のサイズが大きいほどこの効果は高くなります。1 MB 未満のスープ要素では外部ストレージはお勧めしません。外部ストレージを使用するには、次の操作を実行します。1. スープ指定オブジェクトを作成します。スープ名、および外部ストレージを含む機能のリストをこのオブ

ジェクトに設定します。2. スープ名ではなくスープ指定オブジェクトを取るスープ登録メソッドを使用して、スープを登録します。3. スープの登録後にスープ指定を変更するには、スープ指定オブジェクトを取る alterSoup メソッドを使

用します。

重要: SmartStoreは外部要素を通常のスープ要素と同様に処理しますが、唯一の例外として、外部ストレージでは JSON1 インデックスを使用できません。外部ストレージと JSON1 インデックスを使用するスープを登録しようとすると、SmartStore でエラーが発生します。

このセクションの内容:

スープ指定外部ストレージなどのSmartStore特殊機能を使用するスープを登録または変更するには、単なるスープ名ではなくスープ指定を渡します。SmartStore には、スープ指定オブジェクトを作成および取得するためのメソッドが用意されています。外部ストレージを使用するスープの登録外部ストレージのスープ登録には、通常のスープ登録とは異なる API が必要です。スープ指定オブジェクトを取る登録メソッドを使用します。外部ストレージを使用するスープの変更外部ストレージなどの特殊機能を使用するスープを変更するには、スープ指定オブジェクトを取るalterSoup メソッドを使用します。

スープ指定外部ストレージなどの SmartStore 特殊機能を使用するスープを登録または変更するには、単なるスープ名ではなくスープ指定を渡します。SmartStore には、スープ指定オブジェクトを作成および取得するためのメソッドが用意されています。スープ指定オブジェクトで、スープ名およびスープで使用する SmartStore 特殊機能のリストを指定します。次に、スープ指定オブジェクトを registerSoupWithSpecメソッドまたは alterSoupメソッドに渡します。

227

大きいスープ要素での外部ストレージの使用オフライン管理

メモ: 現在、SmartStore には 1 つの特殊機能、外部ストレージのみが定義されています。

Android ネイティブスープ指定作成メソッド (SoupSpec.java)

public SoupSpec(String soupName) // for future usepublic SoupSpec(String soupName, String... features)

スープ指定取得メソッド (SmartStore.java)

public SoupSpec getSoupSpec(String soupName)

iOS ネイティブスープ指定作成メソッド (SFSoupSpec.h)

+ (SFSoupSpec *)newSoupSpec:(NSString *)soupName withFeatures:(NSArray *)features;+ (SFSoupSpec *)newSoupSpecWithDictionary:(NSDictionary *)dictionary;

スープ指定取得メソッド (SFSmartStore.h)

- (SFSoupSpec*)attributesForSoup:(NSString*)soupName;

JavaScript

スープ指定作成メソッド (cordova.force.smartstore.js、react.force.smartstore.js)

SoupSpec(soupName, features)

スープ指定取得メソッド (cordova.force.smartstore.js、react.force.smartstore.js)

getSoupSpecs(soupName)

外部ストレージを使用するスープの登録外部ストレージのスープ登録には、通常のスープ登録とは異なる API が必要です。スープ指定オブジェクトを取る登録メソッドを使用します。スープ指定は、スープがサポートする特殊機能のリストと共にスープ名が含まれるオブジェクトです。この場合、機能リストに「外部ストレージ」の Mobile SDK 言語固有の識別子を含めます。

Android ネイティブスープ指定登録メソッド (SmartStore.java)

public void registerSoupWithSpec(SoupSpec soupSpec,IndexSpec[] indexSpecs)

228

大きいスープ要素での外部ストレージの使用オフライン管理

iOS ネイティブスープ指定登録メソッド (SFSmartStore.h)

- (BOOL)registerSoupWithSpec:(SFSoupSpec*)soupSpecwithIndexSpecs:(NSArray*)indexSpecs

error:(NSError**)error;

JavaScript

スープ指定登録メソッド (cordova.force.smartstore.js、react.force.smartstore.js)

registerSoupWithSpec(isGlobalStore, soupSpec, indexSpecs,successCB, errorCB)

外部ストレージを使用するスープの変更外部ストレージなどの特殊機能を使用するスープを変更するには、スープ指定オブジェクトを取る alterSoup

メソッドを使用します。

Android ネイティブスープ指定変更メソッド (SmartStore.java)

public void alterSoup(String soupName,SoupSpec soupSpec,IndexSpec[] indexSpecs,boolean reIndexData)throws JSONException

iOS ネイティブスープ指定変更メソッド (SFSmartStore.h)

- (BOOL) alterSoup:(NSString*)soupNamewithSoupSpec:(SFSoupSpec*)soupSpec

withIndexSpecs:(NSArray*)indexSpecsreIndexData:(BOOL)reIndexData;

JavaScript

スープ指定変更メソッド (cordova.force.smartstore.js、react.force.smartstore.js)

alterSoupWithSpec(isGlobalStore, soupName, soupSpec,indexSpecs, reIndexData, successCB, errorCB)

229

大きいスープ要素での外部ストレージの使用オフライン管理

スープ要素の削除従来より、SmartStore のメソッドでは要素 ID の配列を指定してスープ要素を削除できます。通常これを行うには、候補 ID を取得する事前クエリを実行してから、削除を実行するメソッドをコールします。Mobile SDK 4.2 では SmartStore が強化され、要素削除メソッドにクエリオプションが追加されました。このオプションではクエリのみを指定し、SmartStoreはそのクエリに適合するすべての要素を削除します。この方法では 1 回のコールでクエリと削除操作の両方が行われるため、パフォーマンスが向上します。

ハイブリッドアプリケーションハイブリッドアプリケーションでは、3 つ目のパラメータを使用して ID 配列または SmartStore クエリ指定を渡します。removeFromSoup(isGlobalStore, soupName, entryIdsOrQuerySpec,

successCB, errorCB)

成功とエラーのコールバックに加えて、この関数は次の引数を取ります。

表 7 : パラメータ引数の説明パラメータ名

ブール型。この操作が認証済みと未認証のどちらのSmartStore データベースで行われるかを示します。

isGlobalStore

文字列型。スープの名前を渡します。soupName

配列または QuerySpec オブジェクト。スープの名前を渡します。

entryIdsOrQuerySpec

Android ネイティブアプリケーションエントリを削除する Android ネイティブメソッドでは、トランザクションを手動で処理するか、メソッドでトランザクションを透過的に処理させるかを選択できます。handleTx 引数を false に設定すると、コールの前に手動でトランザクションを開始し、コール後に手動で終了する必要があります。handleTxが含まれないオーバーロードを使用する場合、または handleTx を false に設定した場合、Mobile SDK が自動的にトランザクションを処理します。Android ネイティブアプリケーションで ID 配列によってエントリを削除するには、次のいずれかのメソッドをコールします。public void delete(String soupName, Long... soupEntryIds)public void delete(String soupName, Long[] soupEntryIds, boolean handleTx)

Android ネイティブアプリケーションでクエリによってエントリを削除するには、次のいずれかのメソッドをコールします。public void deleteByQuery(String soupName, QuerySpec querySpec)public void deleteByQuery(String soupName, QuerySpec querySpec, boolean handleTx)

230

スープ要素の削除オフライン管理

iOS ネイティブアプリケーションiOS ネイティブアプリケーションで ID 配列によってエントリを削除するには、次のメソッドをコールします。- (void)removeEntries:(NSArray*)entryIds fromSoup:(NSString*)soupName error:(NSError**)error;

iOS ネイティブアプリケーションでクエリによってエントリを削除するには、次のいずれかのメソッドをコールします。- (void)removeEntriesByQuery:(SFQuerySpec*)querySpec

fromSoup:(NSString*)soupName;- (void)removeEntriesByQuery:(SFQuerySpec*)querySpec

fromSoup:(NSString*)soupNameerror:(NSError **)error;

スープの管理SmartStore には、スープメタデータを取得して、スープレベルの他の操作を実行できるユーティリティ機能が用意されています。この機能は、ハイブリッド、Android ネイティブ、および iOS ネイティブアプリケーションで使用できます。

ハイブリッドアプリケーションJavaScript の各スープ管理関数が 2 つのコールバック関数を取ります。1 つは要求されたデータを返す成功コールバックで、もう 1 つはエラーコールバックです。成功コールバックは、そのコールバックを使用するスープ管理関数によって異なります。エラーコールバックは、エラーの説明文字列を含む 1 つの引数を取ります。たとえば、エラーコールバック関数は次のように定義できます。function(e) { alert(“ERROR: “ + e);}

JavaScript でスープ管理関数をコールするには、最初に Cordova プラグインを呼び出して SmartStoreオブジェクトを初期化してから、関数をコールします。次の例では、名前付きのコールバック関数を個別に定義していますが、匿名のコールバック関数をインラインで定義することもできます。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);

231

スープの管理オフライン管理

Android ネイティブアプリケーションSmartStore 対応の Android ネイティブアプリケーションでスープ管理 API を使用するには、SmartStore 共有インスタンスで次のメソッドをコールします。private SmartStoreSDKManager sdkManager;private SmartStore smartStore;sdkManager = SmartStoreSDKManager.getInstance();smartStore = sdkManager.getSmartStore();smartStore.clearSoup("user1Soup");

iOS ネイティブアプリケーションiOS ネイティブアプリケーションでスープ管理 API を使用するには、SFSmartStore.h をインポートします。SFSmartStore 共有インスタンスでスープ管理メソッドをコールします。次のいずれかの SFSmartStore クラスメソッドを使用して、共有インスタンスを取得します。現在のユーザの SmartStore インスタンスを使用する場合

+ (id)sharedStoreWithName:(NSString*)storeName;

指定したユーザの SmartStore インスタンスを使用する場合+ (id)sharedStoreWithName:(NSString*)storeName

user:(SFUserAccount *)user;

次に例を示します。self.store = [SFSmartStore sharedStoreWithName:kDefaultSmartStoreName];if ([self.store soupExists:@"Accounts"]) {

[self.store removeSoup:@"Accounts"];}

このセクションの内容:

データベースサイズの取得データベースによるハードディスクの消費容量をクエリするには、データベースサイズメソッドをコールします。スープのクリアスープのすべてのエントリを削除するには、スープクリアメソッドをコールします。スープのインデックス指定の取得スープのインデックス指定を検証または表示する場合は、適切なインデックス指定取得メソッドをコールします。スープの既存のインデックス指定の変更既存のインデックス指定を変更するには、適切なスープ変更メソッドをコールします。

232

スープの管理オフライン管理

スープへの再インデックス付け以前にスープを変更しデータへの再インデックス付けを行わなかったが、その後スープの全要素に適切なインデックスを付けることにした場合は、再インデックス付けを行います。alterSoup()とreindexSoup()

の両方は、他のインデックス指定のタイプよりも JSON1 インデックス指定の変換または作成で優れたパフォーマンスを発揮します。スープの削除スープを削除すると消去されます。ユーザがサインアウトすると、すべてのスープが自動的に削除されます。サインアウト以外でスープを削除する場合は、適切なスープ削除メソッドをコールします。

関連トピック:

既存の Android アプリケーションへの SmartStore の追加

データベースサイズの取得データベースによるハードディスクの消費容量をクエリするには、データベースサイズメソッドをコールします。

ハイブリッドアプリケーションハイブリッドアプリケーションでは、次の関数をコールします。navigator.smartstore.getDatabaseSize(successCallback, errorCallback)

成功コールバックは、データベースサイズ (バイト単位) を含む 1 つのパラメータをサポートします。次に例を示します。function(dbSize) { alert("db file size is:" + dbSize + " bytes"); }

Android ネイティブアプリケーションAndroid アプリケーションでは、次のメソッドをコールします。public int getDatabaseSize ()

iOS ネイティブアプリケーションAndroid アプリケーションでは、次のメソッドをコールします。- (long)getDatabaseSize

スープのクリアスープのすべてのエントリを削除するには、スープクリアメソッドをコールします。

233

スープの管理オフライン管理

ハイブリッドアプリケーションハイブリッドアプリケーションでは、次の関数をコールします。navigator.smartstore.clearSoup(soupName, successCallback, errorCallback)

成功コールバックは、スープ名を含む 1 つのパラメータをサポートします。次に例を示します。function(soupName) { alert("Soup " + soupName + " was successfully emptied."); }

Android アプリケーションAndroid アプリケーションでは、次のメソッドをコールします。public void clearSoup ( String soupName )

iOS アプリケーションiOS アプリケーションでは、次のメソッドをコールします。- (void)clearSoup:(NSString*)soupName;

スープのインデックス指定の取得スープのインデックス指定を検証または表示する場合は、適切なインデックス指定取得メソッドをコールします。

ハイブリッドアプリケーションハイブリッドアプリケーションでは、次の関数をコールします。getSoupIndexSpecs()

この関数は、成功およびエラーコールバック関数の他に、1 つの引数 soupNameを取ります。この引数はスープの名前です。次に例を示します。navigator.smartstore.getSoupIndexSpecs(soupName, successCallback,

errorCallback)

成功コールバックは、インデックス指定の配列を含む 1 つのパラメータをサポートします。次に例を示します。function(indexSpecs) { alert("Soup " + soupName +

" has the following indexes:" + JSON.stringify(indexSpecs); }

Android アプリケーションAndroid アプリケーションでは、次のメソッドをコールします。public IndexSpec [] getSoupIndexSpecs ( String soupName )

234

スープの管理オフライン管理

iOS アプリケーションiOS アプリケーションでは、次のメソッドをコールします。- (NSArray*)indicesForSoup:(NSString*)soupName

スープの既存のインデックス指定の変更既存のインデックス指定を変更するには、適切なスープ変更メソッドをコールします。データに再インデックス付けする場合は、次のパフォーマンスに関するヒントに留意してください。• 再インデックス付けはコストがかかる可能性があるため、reIndexData引数は省略可能です。reIndexData

を false に設定すると、スループットが大幅に加速するものと予想されます。• すでにデータが含まれているスープを変更すると、アプリケーションのパフォーマンスが低下することが

あります。reIndexData を true に設定すると、パフォーマンスヒットが悪化します。• パフォーマンスの指針として、reIndexData が true に設定されている場合の alterSoup() 操作の所要時

間は 1000 レコードあたり 1 秒です。個別のパフォーマンスは、デバイスの性能、要素のサイズ、およびインデックスの数によって異なります。

• alterSoup() および reindexSoup() は、他のインデックス指定のタイプよりも JSON1 インデックス指定の変換または作成で優れたパフォーマンスを発揮します。

• JSON1 インデックス指定では、挿入のパフォーマンスが向上します。• JSON1 インデックス指定ではデータベースサイズが小さくなります。• クエリのパフォーマンスは、一般的に JSON1 インデックス指定による影響はありません。• スープの変更が完了するまで SmartStore の他の操作は実行できません。• ユーザがアプリケーションを終了するなどして操作が中断された場合は、アプリケーションで SmartStore

データベースが再度開かれたときにその操作が自動的に再開されます。

外部ストレージを使用するインデックス指定の変更外部ストレージ機能を使用するスープを登録した場合、「外部ストレージを使用するスープの変更」で説明されている alterSoup メソッドを使用します。

ハイブリッドアプリケーションハイブリッドアプリケーションでは、次の関数をコールします。navigator.smartstore.alterSoup(soupName, indexSpecs, reIndexData,

successCallback, errorCallback)

成功とエラーのコールバックに加えて、この関数は次の引数を取ります。

表 8 : パラメータ引数の説明パラメータ名

文字列型。スープの名前を渡します。soupName

235

スープの管理オフライン管理

引数の説明パラメータ名

配列型。インデックス指定のインデックスエントリのセットを渡します。

indexSpecs

ブール型。インデックス指定を置換後に関数でスープに再インデックス付けするかどうかを示します。

reIndexData

成功コールバックは、スープ名を含む 1 つのパラメータをサポートします。次に例を示します。function(soupName) { alert("Soup " + soupName +

" was successfully altered"); }

次の例では、スープの単純な変更を行います。最初に、開発者が name 項目および address 項目にインデックス付けされる項目を定義し、エージェントレコードを更新/挿入します。navigator.smartstore.registerSoup("myAgents",

[{path:'name', type:'string'},{path:'address', type:'string'}]);

navigator.smartstore.upsertSoupEntries("myAgents",[{name:'James Bond',address:'1 market st',agentNumber:"007"}]);

過去の経験から、ユーザがエージェントの addressではなく「agentNumber」を使用したクエリを望んでいることが判明している場合は、addressへのインデックスを削除して、agentNumberへのインデックスを追加します。navigator.smartstore.alterSoup("myAgents", [{path:'name',type:'string'}, {path:'agentNumber',type:'string'}], true);

メモ: 開発者が reIndexData パラメータを false に設定した場合は、agentNumber に対するクエリで、挿入済みのエントリ (「James Bond」) が検索されません。ただし、nameでレコードをクエリすることは可能です。agentNumber によるクエリをサポートするには、最初にnavigator.smartstore.reIndexSoup("myAgents", ["agentNumber"]) をコールする必要があります。

Android ネイティブアプリケーションAndroid ネイティブアプリケーションでは、次のメソッドをコールします。public void alterSoup(String soupName, IndexSpec [] indexSpecs, boolean reIndexData) throwsJSONException

iOS ネイティブアプリケーションiOS ネイティブアプリケーションでは、次のメソッドをコールします。- (BOOL) alterSoup:(NSString*)soupName withIndexSpecs:(NSArray*)indexSpecsreIndexData:(BOOL)reIndexData;

236

スープの管理オフライン管理

スープへの再インデックス付け以前にスープを変更しデータへの再インデックス付けを行わなかったが、その後スープの全要素に適切なインデックスを付けることにした場合は、再インデックス付けを行います。alterSoup() と reindexSoup() の両方は、他のインデックス指定のタイプよりも JSON1 インデックス指定の変換または作成で優れたパフォーマンスを発揮します。

ハイブリッドアプリケーションハイブリッドアプリケーションでは、次の関数をコールします。navigator.smartstore.reIndexSoup(soupName, listOfPaths, successCallback, errorCallback)

この関数は、成功およびエラーコールバック関数の他に、1 つの引数 soupNameを取ります。この引数はスープの名前です。たとえば、次の関数は追加の引数を取ります。

引数の説明パラメータ名

文字列型。スープの名前を渡します。soupName

配列型。再インデックス付けするインデックスパスのリスト。

listOfPaths

成功コールバックは、スープ名を含む 1 つのパラメータをサポートします。次に例を示します。function(soupName) { alert("Soup " + soupName +

" was successfully re-indexed."); }

Android アプリケーションAndroid アプリケーションでは、次のメソッドをコールします。public void reIndexSoup(String soupName, String[] indexPaths, boolean handleTx)

iOS アプリケーションiOS アプリケーションでは、次のメソッドをコールします。- (BOOL) reIndexSoup:(NSString*)soupName

withIndexPaths:(NSArray*)indexPaths

スープの削除スープを削除すると消去されます。ユーザがサインアウトすると、すべてのスープが自動的に削除されます。サインアウト以外でスープを削除する場合は、適切なスープ削除メソッドをコールします。

237

スープの管理オフライン管理

ハイブリッドアプリケーションハイブリッドアプリケーションでは、次の関数をコールします。navigator.smartstore.removeSoup(soupName,successCallback,errorCallback);

Android アプリケーションAndroid アプリケーションでは、次のメソッドをコールします。public void dropSoup ( String soupName )

iOS アプリケーションiOS アプリケーションでは、次のメソッドをコールします。- (void)removeSoup:(NSString*)soupName

グローバル SmartStore の使用通常は SmartStore インスタンスを特定の顧客のログイン情報に関連付けますが、特別な要件でグローバルインスタンスにアクセスすることもできます。特定の状況では、一部のアプリケーションで、Salesforce 認証に関連付けられていない SmartStore インスタンスへのアクセスが必要になります。このような状況は、アプリケーションの状態や、Salesforceユーザ、組織、またはコミュニティに依存しない他のデータを保存するアプリケーションで発生する場合があります。Mobile SDK

では、アプリケーションのライフサイクル全体で保持される SmartStore のグローバルインスタンスへのアクセスを提供します。グローバルSmartStoreに保存されるデータは、ユーザ認証に依存しないため、ログアウト時に削除されません。グローバル SmartStore は、ログアウト後もそのまま保持されるため、アプリケーションの終了時にそのデータをクリアする必要があります。Mobile SDK には、このための API が用意されています。

重要: ユーザ固有のデータをグローバル SmartStore に保存しないでください。このようにすると、ユーザデータがユーザのログアウト後も保持される可能性があるため、Mobile SDK セキュリティ要件に違反します。

Android APIAndroid の場合、SmartStoreSDKManager のインスタンスを介してグローバル SmartStore にアクセスします。

238

グローバル SmartStore の使用オフライン管理

• public SmartStore getGlobalSmartStore(String dbName)

指定したデータベース名のグローバル SmartStore インスタンスを返します。dbName には、「smartstore」以外の任意の文字列を設定できます。デフォルトのグローバル SmartStore データベースを使用するには、dbName を null に設定します。

• public boolean hasGlobalSmartStore(String dbName)

指定したデータベース名のグローバルSmartStoreインスタンスが存在しているかどうかをチェックします。デフォルトのグローバル SmartStore の存在を確認するには、dbName を null に設定します。

• public void removeGlobalSmartStore(String dbName)

指定したグローバルSmartStoreデータベースを削除します。この名前には、「smartstore」以外の任意の文字列を設定できます。デフォルトのグローバル SmartStore を削除するには、dbName を null に設定します。

iOS APIiOS の場合、SFSmartStore のインスタンスを介してグローバル SmartStore にアクセスします。• + (id)sharedGlobalStoreWithName:(NSString *)storeName

指定したデータベース名のグローバルSmartStoreインスタンスを返します。storeNameには、「defaultStore」以外の任意の文字列を設定できます。デフォルトのグローバル SmartStore を使用するには、storeName をkDefaultSmartStoreName に設定します。

• + (void)removeSharedGlobalStoreWithName:(NSString *)storeName

指定したグローバル SmartStoreデータベースを削除します。storeNameには、「defaultStore」以外の任意の文字列を設定できます。デフォルトのグローバル SmartStore を使用するには、storeName をkDefaultSmartStoreName に設定します。

ハイブリッド APISmartStoreプラグインの JavaScript メソッドは、グローバルSmartStoreを使用するかどうかを示す省略可能な Boolean

引数を取ります。この引数が false または指定されていない場合、Mobile SDK はデフォルトのユーザストアを使用します。次に例を示します。var querySoup = function ([isGlobalStore, ]soupName, querySpec,

successCB, errorCB);

SmartStore インスペクタを使用したテストテスト中に SmartStoreの操作を確認することは面倒で時間がかかります。SmartStoreインスペクタでこの問題を解消できます。テスト中、SmartStore データがコードで意図したとおりに処理されているかどうかを確認できると便利です。SmartStore インスペクタには、こうしたテストを行うためのモバイル UI が用意されています。SmartStore インスペクタでは、次のことができます。• スープメタデータ (スープの名前やインデックス指定など) を検証する。

239

SmartStore インスペクタを使用したテストオフライン管理

• スープのコンテンツをクリアする。• スマート SQL クエリを実行する。

メモ: SmartStoreインスペクタは、テストとデバッグのみのためにあります。アプリケーションの最終バージョンを作成する前に、SmartStore インスペクタへの参照をすべて削除してください。

ハイブリッドアプリケーションSmartStore インスペクタを起動するには、SmartStore プラグインオブジェクトで showInspector() をコールします。HTML でのインストール手順は、次のとおりです。<!-- include Cordova --><script src="cordova.js"></script>

<script> ブロックまたは参照先の JavaScript ライブラリの場合var sfSmartstore = function() {return cordova.require("com.salesforce.plugin.smartstore");};sfSmartstore().showInspector();

Android ネイティブアプリケーションAndroid ネイティブアプリケーションでは、SmartStoreInspectorActivity クラスを使用して、SmartStore

インスペクタを起動します。final Intent i = new Intent(activity,

SmartStoreInspectorActivity.class);activity.startActivity(i);

iOS ネイティブアプリケーションiOS ネイティブアプリケーションでは、クラスレベルの present メッセージを送信して、SmartStore インスペクタを起動します。#import <SalesforceSDKCore/SFSmartStoreInspectorViewController.h>...[[[SFSmartStoreInspectorViewController alloc]

initWithStore:self.store] present:self];

SFSmartStoreInspectorViewController:presentクラスは、通常はそれ自体のライフサイクルを管理します。何らかの例外的な理由で SFSmartStoreInspectorViewController:present を破棄する場合は、クラスレベルの SFSmartStoreInspectorViewController:dismiss メッセージを送信します。[SFSmartStoreInspectorViewController dismiss];

擬似 SmartStore の使用コンテナ外で実行しながら SmartStore を使用するコードの開発とテストを容易にするため、エミュレートされた SmartStore を使用できます。

240

擬似 SmartStore の使用オフライン管理

MockSmartStore は、データをローカルストレージ (または必要に応じてメモリのみ) に保存する SmartStore のJavaScript 実装です。external/shared/test ディレクトリには、次のファイルがあります。• MockCordova.js — コンテナ外でプラグインのテストのみを目的とする、Cordova 関数の最小限の実装。

Cordova プラグインコールを受信します。• MockSmartStore.js — コンテナ外での開発およびテストのみを目的とする、SmartStoreの JavaScript 実装。

また、SmartStore Cordova プラグインコールを受信し、MockSmartStore を使用して処理します。SmartStore を使用してアプリケーションを開発する場合、次の変更を加え、コンテナ外でアプリケーションをテストします。• cordova.js ではなく MockCordova.js を含める。• MockSmartStore.js を含める。MockSmartStore の例を確認するには、external/shared/test/test.html をチェックアウトします。

同じ発生元のポリシー同じ発生元のポリシーでは、同じサイトのページでスクリプトを実行し、相互のメソッドおよびプロパティに制限なしでアクセスできます。また、異なるサイトのすべてのページで、ほとんどのメソッドおよびプロパティへのアクセスがブロックされます。コンテナでは同じ発生元のポリシーが Web ビューで無効になるため、同じ発生元のポリシーに関する制限は、コンテナ内でコードを実行する場合には問題になりません。ただし、リモート API をコールする場合は、同じ発生元のポリシーに関する制限を考慮する必要があります。ブラウザには同じ発生元のポリシーを無効にする方法が備えられており、特定のブラウザを使用した場合の方法を調査できます。ローカルファイルシステムから読み込まれた JavaScript ファイルから Force.comに対して XHR

コールを行う場合は、同じ発生元のポリシーを無効にしてブラウザを起動する必要があります。次の記事は、一般的ないくつかのブラウザで同じ発生元のポリシーを無効にする方法を説明しています: 「Getting Around

Same-Origin Policy in Web Browsers (Web ブラウザでの同じ発生元のポリシーの回避)」。

認証MockSmartStore を使用する認証では、アクセストークンと更新トークンを実際のセッションから取得し、そのコードを JavaScript アプリケーションで手動で作成する必要があります。また、forcetk.mobilesdk JavaScript

Toolkit の初期化にもこれらのトークンが必要です。

メモ:

• MockSmartStore は、データを暗号化せず、本番アプリケーションでの使用を目的としていません。• 現在、MockSmartStore では、次の形式のスマート SQL クエリがサポートされています。

– SELECT...WHERE...。次に例を示します。SELECT {soupName:selectField} FROM {soupName} WHERE {soupName:whereField} IN(values)

– SELECT...WHERE...ORDER BY...。次に例を示します。SELECT {soupName:_soup} FROM {soupName} WHERE {soupName:whereField} LIKE 'value'ORDER BY LOWER({soupName:orderByField})

241

擬似 SmartStore の使用オフライン管理

– SELECT count(*) FROM {soupName}

MockSmartStore では、build*QuerySpec() 関数で処理される、より単純なタイプのスマート SQL ステートメントは直接サポートされていません。代わりに、目的に合ったクエリ指定の関数が使用されます。

関連トピック:

スープからのデータの取得

SmartSync を使用した Salesforce オブジェクトへのアクセス

SmartSync ライブラリは、開発者が Salesforce データベースとモバイルアプリケーション間で容易にデータを同期できるようにする API のコレクションです。データの取得およびサーバエンドポイントへの投稿、デバイスでのデータのキャッシュ、およびキャッシュされたデータの読み込みの手段を提供します。SmartSyncでは、同期操作用にキャッシュポリシーを事前定義して、オフラインおよびオンラインシナリオでキャッシュされたデータとサーバデータ間のやりとりを微調整します。SmartSync の便利なメソッドを使用すると、sObject メタデータの取得、最近使用されたオブジェクトのリストの取得、SOQL および SOSL クエリの作成など、よく行うネットワーク作業を自動化できます。

Mobile SDK 4.2 の SmartSync の新機能SmartSync では、「ゴースト」スープ要素を削除するメソッドが提供されるようになりました。ゴースト要素は、サーバで削除された後や下位同期クエリに一致しなくなった後にスープに残るスープエントリです。「下位同期操作後の「ゴースト」レコードの処理」を参照してください。

ネイティブアプリケーションでの SmartSync の使用SmartSync ネイティブライブラリには、オフライン対応アプリケーションの開発を簡略化するネイティブの iOS

API および Android API が用意されています。このネイティブ機能のサブセットは、Cordova プラグインを介してハイブリッドアプリケーションでも使用できます。SmartSyncライブラリには、Android と iOS で同様のアーキテクチャおよび機能が用意され、各プラットフォームのネイティブ言語で示されます。両方に共通の分かりやすい機能的な概念が採用されています。• Salesforce REST API をコールして、Salesforce オブジェクトメタデータをクエリする。• 取得したオブジェクトデータをオフラインで使用できるようにローカルに安全に保存する。• デバイスがオフラインからオンライン状態になったときにデータの変更を同期する。SmartSync ネイティブライブラリでは、次の操作を実行できます。• サーバエンドポイントとやりとりして、データを取得および投稿する。SmartSyncヘルパー API は、使用頻度

が最も高いエンドポイントをエンコードします。これらの API は、sObject メタデータの取得、MRU (最近使用した) オブジェクトのリストの取得、SOQL および SOSL クエリの作成に役立ちます。カスタムクラスで指定した任意のエンドポイントを使用することもできます。

242

SmartSync を使用した Salesforce オブジェクトへのアクセス

オフライン管理

• Salesforce レコードおよびメタデータを取得し、事前定義されたキャッシュポリシーの 1 つを使用してデバイスにキャッシュする。

• レコードをオフラインで編集し、SmartStore にオフラインで保存する。• ローカルで変更されたデータを Salesforce クラウドに転送して、レコードのバッチを同期する。

SmartSync コンポーネントSmartSync アーキテクチャの基盤となるコンポーネントは次のとおりです。同期マネージャ

• Android クラス: com.salesforce.androidsdk.smartsync.manager.SyncManager

• iOS クラス: SFSmartSyncSyncManager

sObject のサイズの大きなバッチをサーバと SmartStore 間で同期する API を提供します。このクラスは、メタデータマネージャとは独立して機能し、最も簡単で最も一般的な同期操作の実行を目的とします。同期マネージャは、sObject のセットをサーバから SmartStore にダウンロードする「下位同期」、およびローカルsObject をサーバにアップロードする「上位同期」を行うことができます。同期マネージャは、次のユーティリティクラスと連動します。同期状態クラス

• Android: com.salesforce.androidsdk.smartsync.util.SyncState

• iOS: SFSyncState

– 同期操作の状態を追跡します。この操作の状態は次のとおりです。• 新規 — 同期操作が開始されましたが、サーバとのトランザクションはまだ始まっていませ

ん。• 実行中 — 同期操作がサーバと同期トランザクションのネゴシエーションを行っています。• 完了 — 同期操作が正常に完了しました。• 失敗 — 同期操作に失敗しました。

同期ターゲットクラス• Android: com.salesforce.androidsdk.smartsync.util.SyncTarget

• iOS: SFSyncTarget

– 「下位同期」操作中にダウンロードする sObject を指定します。

同期オプションクラス• Android: com.salesforce.androidsdk.smartsync.util.SyncOptions

• iOS: SFSyncOptions

– 「上位同期」操作の設定オプションを指定します。オプションには、同期する項目名のリストが示されます。

メタデータマネージャ• Android クラス: com.salesforce.androidsdk.smartsync.manager.MetadataManager

• iOS クラス: SFSmartSyncMetadataManager

243

ネイティブアプリケーションでの SmartSync の使用オフライン管理

データ読み込み機能を実行します。このクラスは、同期マネージャのプロトコルがサポートするものよりも高機能のクエリおよび設定を処理する場合に役立ちます。たとえば、メタデータマネージャの API には次の機能があります。• SmartScope オブジェクト型を読み込む。• sObject の MRU リストを読み込む。結果はグローバルにすることも、特定の sObject に限定することもで

きます。• describe API を使用して、sObject の完全オブジェクト定義を読み込む。• 組織で使用可能なすべての sObject のリストを読み込む。• sObject が検索可能かどうかを判断し、検索可能な場合は sObject 型の検索レイアウトを読み込む。• sObject 型の色リソースを読み込む。• sObject をサーバで表示済みとマークし、その sObject 型の MRU リストの一番上に移動する。サーバとやりとりするために、MetadataManager は次の標準の Mobile SDK REST API クラスを使用します。• Android: RestClient、RestRequest

• iOS: SFRestAPI、SFRestRequest

また、SmartSync キャッシュマネージャを使用して、キャッシュとの間でデータの書き込みと読み取りを行います。

キャッシュマネージャ• Android クラス: com.salesforce.androidsdk.smartsync.manager.CacheManager

• iOS クラス: SFSmartSyncCacheManager

デバイス上のキャッシュとの間で、オブジェクト、オブジェクト型、オブジェクトレイアウトの書き込みと読み取りを行います。また、指定したキャッシュの種類およびキャッシュキーを削除するメソッドを提供します。キャッシュマネージャは、キャッシュデータを、SQLCipher がサポートするSmartStoreデータベースに保存します。キャッシュマネージャはアプリケーションとやりとりできないわけではありませんが、メタデータマネージャがその主要クライアントで、通常はメタデータマネージャがアプリケーションとのすべてのやりとりを処理します。

SOQL ビルダー• Android クラス: com.salesforce.androidsdk.smartsync.util.SOQLBuilder

• iOS クラス: SFSmartSyncSoqlBuilder

クエリの句を個々に指定して、SOQL クエリステートメントを簡単に作成できるようにするユーティリティクラスです。

SOSL ビルダー• Android クラス: com.salesforce.androidsdk.smartsync.util.SOSLBuilder

• iOS クラス: SFSmartSyncSoslBuilder

クエリの句を個々に指定して、SOSL クエリステートメントを簡単に作成できるようにするユーティリティクラスです。

SmartSyncSDKManager (Android のみ)

Android の場合は、SmartSync アプリケーションが基本アプリケーションとは異なる SDK マネージャオブジェクトを使用します。App クラスにより、SalesforceSDKManager ではなく、SmartSyncSDKManager が

244

ネイティブアプリケーションでの SmartSync の使用オフライン管理

拡張されます。forcedroid バージョン 3.0 以降を使用して SmartStore アプリケーションを作成する場合は、この置換が自動的に行われます。この変更は、Android のネイティブとハイブリッドの両方のSmartSyncアプリケーションに適用されます。

メモ: マルチユーザの切り替えをサポートするために、SmartSync ではユーザアカウントごとにそのコンポーネントの固有のインスタンスを作成します。

キャッシュポリシーアプリケーションデータを更新するときに、キャッシュポリシーを指定して、SmartSyncにキャッシュの処理方法を指示できます。サーバデータと同期する、サーバの更新に失敗したときは代わりにキャッシュを使用する、キャッシュをクリアする、キャッシュを無視するなどを選択できます。Android の場合、キャッシュポリシーは com.salesforce.androidsdk.smartsync.manager.CacheManager.CachePolicy クラスで定義されます。iOS の場合は、SFSmartSyncCacheManager.h で定義される SFDataCachePolicy 列挙の一部です。データを読み込むメタデータマネージャのメソッドをコールするたびに、キャッシュポリシーを指定します。Android MetadataManager データの読み込みメソッドの例を次に示します。public List<SalesforceObjectType>

loadSmartScopeObjectTypes(CachePolicy cachePolicy,long refreshCacheIfOlderThan);

public List<SalesforceObject> loadMRUObjects(String objectTypeName,int limit, CachePolicy cachePolicy, long refreshCacheIfOlderThan,String networkFieldName);

public List<SalesforceObjectType> loadAllObjectTypes(CachePolicy cachePolicy, long refreshCacheIfOlderThan);

public SalesforceObjectType loadObjectType(String objectTypeName, CachePolicy cachePolicy,long refreshCacheIfOlderThan);

public List<SalesforceObjectType> loadObjectTypes(List<String> objectTypeNames, CachePolicy cachePolicy,long refreshCacheIfOlderThan);

また、キャッシュを再読み込みする時期かどうかをキャッシュマネージャが判断しやすくするキャッシュポリシーも指定できます。Android:

public boolean needToReloadCache(boolean cacheExists,CachePolicy cachePolicy, long lastCachedTime, long refreshIfOlderThan);

iOS:

- (BOOL)needToReloadCache:(BOOL)cacheExistscachePolicy:(SFDataCachePolicy)cachePolicylastCachedTime:(NSDate *)cacheTimerefreshIfOlderThan:(NSTimeInterval)refreshIfOlderThan;

キャッシュポリシーのリストを次に示します。

245

ネイティブアプリケーションでの SmartSync の使用オフライン管理

表 9 : キャッシュポリシー説明キャッシュポリシー (iOS)

キャッシュデータを無視します。常にサーバから最新のデータを取得します。

iOS:IgnoreCacheData

Android:IGNORE_CACHE_DATA

サーバからデータの読み込みを試行しますが、サーバへのコールに失敗した場合は代わりにキャッシュデータを使用します。

iOS:ReloadAndReturnCacheOnFailure

Android:RELOAD_AND_RETURN_CACHE_ON_FAILURE

キャッシュのデータを返し、サーバへのコールは試行しません。

iOS:ReturnCacheDataDontReload

Android:RETURN_CACHE_DATA_DONT_RELOAD

サーバからデータを再読み込みし、キャッシュを新しいデータで更新します。

iOS:ReloadAndReturnCacheData

Android:RELOAD_AND_RETURN_CACHE_DATA

キャッシュデータが古くなっている場合 (指定したタイムアウトを経過した場合) はサーバか

iOS:ReloadIfExpiredAndReturnCacheData

らデータを再読み込みします。それ以外の場合は、キャッシュのデータを返します。

Android:RELOAD_IF_EXPIRED_AND_RETURN_CACHE_DATA

キャッシュをクリアし、サーバからデータを再読み込みしません。

iOS:InvalidateCacheDontReload

Android:INVALIDATE_CACHE_DONT_RELOAD

キャッシュをクリアし、サーバからデータを再読み込みします。

iOS:InvalidateCacheAndReload

Android:INVALIDATE_CACHE_AND_RELOAD

オブジェクト表現メタデータマネージャを使用する場合、メタデータマネージャの読み込みメソッドをコールした結果としてSmartSyncモデル情報を取得できます。メタデータマネージャは現在のユーザの組織からデータを読み込み、それを次の 3 つのクラスのいずれかで表現します。

246

ネイティブアプリケーションでの SmartSync の使用オフライン管理

• オブジェクト• オブジェクト種別• オブジェクト種別レイアウト

オブジェクト• Android クラス: com.salesforce.androidsdk.smartsync.model.SalesforceObject

• iOS クラス: SFObject

これらのクラスは、Salesforceの sObject から取得したデータをカプセル化します。オブジェクトクラスは、クエリの結果が含まれる Android の JSONObject または iOS の NSDictionary オブジェクトからデータを読み込みます。その後で、オブジェクトの ID、種別、名前をプロパティとして保存します。JSONObject自体も未加工データとして保存します。

オブジェクト種別• Android クラス: com.salesforce.androidsdk.smartsync.model.SalesforceObjectType

• iOS クラス: SFObjectType

オブジェクト種別クラスは、プレフィックス、名前、表示ラベル、複数形の表示ラベル、項目など、sObject の詳細を保存します。

オブジェクト種別レイアウト• Android クラス: com.salesforce.androidsdk.smartsync.model.SalesforceObjectTypeLayout

• iOS クラス: SFObjectTypeLayout

オブジェクト種別レイアウトクラスは、組織の sObject に対して定義されている列形式の検索レイアウトを取得します (定義されている場合)。レイアウトがない場合、アプリケーションで表示する項目とそれらを表示する形式を自由に選択できます。

関連トピック:

キャッシュポリシー

SmartSync ネイティブアプリケーションの作成forceios バージョン 3.0 以降では SmartSyncネイティブアプリケーションを作成するのに特別な努力は必要ありません。作成する forceios ネイティブアプリケーションには自動的に SmartStoreおよび SmartSyncライブラリが含まれます。Android の場合、forcedroid バージョン 3.0 以降で必要なのは追加のパラメータを 1 つ指定することだけです。forcedroid パラメータをハードコード化している場合は、--usesmartstore=yes を設定します。対話型でforcedroid create を使用する場合、forcedroid から「アプリケーションで SmartStoreまたは SmartSyncを使用しますか?」と尋ねられたら「はい」と答えます。forcedroid 3.0 以降の場合、SmartStoreサポートにSmartSyncライブラリが含まれます。

247

ネイティブアプリケーションでの SmartSync の使用オフライン管理

既存の Android アプリケーションへの SmartSync の追加Mobile SDK 4.0 以降で作成された既存の Android プロジェクト (ハイブリッドまたはネイティブ) に SmartSync を追加する手順を次に示します。1. 現在アプリケーションが Mobile SDK 3.3 以前に構築されている場合は、「以前のリリースからの移行」の説

明に従って、プロジェクトを SDK の最新バージョンにアップグレードします。2. SmartSyncライブラリプロジェクトをプロジェクトに追加します。SmartSyncはSmartStoreを使用するため、プ

ロジェクトがSmartStoreを使用して構築されていない場合は、このライブラリも追加する必要があります。a. Android Studio で、libs/SmartSync プロジェクトをモジュール連動関係に追加します。

3. プロジェクト全体で、SalesforceSDKManager オブジェクトを使用するすべてのコードを、代わりにSmartSyncSDKManager を使用するように変更します。

メモ: プロジェクト全体の検索および置換を実行する場合は、KeyInterfaceインポートは変更せず、そのままにします。import com.salesforce.androidsdk.app.SalesforceSDKManager.KeyInterface;

既存の iOS アプリケーションへの SmartSync の追加SmartSyncをサポートするための既存の iOS プロジェクトのアップグレードは簡単に行うことができます。古いSmartSync アプリケーションを Mobile SDK 4.0 以降にアップグレードしたり、SmartSync を新しい iOS アプリケーションに追加したりするには、次の手順を実行します。Mobile SDK 4.0 では、SmartSync が Mobile SDK コアから独自のライブラリに移動しました。この新しいモジュールは CocoaPods を介してプロジェクトに追加できます。この作業は、podspec を若干変更するだけで済みます。SmartSync は SmartStore に依存しているため、CocoaPods によって自動的に SmartStore が SmartSync プロジェクトに追加されます。ただし、すべてが自動的に行われるわけではありません。SmartStoreを使用するアプリケーションで SmartStoreSDKManager クラスのインスタンスが必要になりましたが、このクラスでは、コードのSalesforceSDKManager が置き換わりません。代わりに、SmartStoreSDKManager をインスタンスクラスとして使用するように、共有 SalesforceSDKManager インスタンスを設定します。1. podspec で、SmartSync をサブ仕様として追加します。

pod 'SalesforceMobileSDK-iOS', :subspecs => ['SmartSync'

]end

2. AppDelegate.m ファイルで次の手順を実行します。a. SmartStoreSDKManager ヘッダーをインポートします。

#import <SmartStore/SmartStoreSDKManager.h>

b. init メソッドで、[SalesforceSDKManager sharedManager] が最初に使用される前に次のコールを追加します。[SalesforceSDKManager setInstanceClass:[SmartStoreSDKManager class]];

248

ネイティブアプリケーションでの SmartSync の使用オフライン管理

このコールでのみ、SmartStoreSDKManager クラスを明示的に参照する必要があります。残りのコードは、以前と同じように機能します。

例については、SmartSyncExplorer サンプルアプリケーションのAppDelegate クラスを参照してください。

データの同期SmartSync ネイティブアプリケーションでは、同期マネージャを使用してデバイスと Salesforce サーバ間のデータを簡単に同期できます。同期マネージャは、「上方」同期 (デバイスからサーバ) または「下方」同期 (サーバからデバイス) のメソッドを提供します。SmartSync アプリケーションのデータ要求はすべて非同期です。非同期であるため、コールする同期メソッドは、サーバの応答をコールバックメソッドまたは定義された更新ブロックで返します。上位同期または下位同期メソッドは、それぞれ同期状態オブジェクトを返します。このオブジェクトには次の情報が含まれます。• 同期操作 ID。この ID を同期マネージャの getSyncStatus メソッドに渡すことで、いつでも操作の進行状

況を確認できます。• 同期パラメータ (スープ名、下位同期操作のターゲット、上位同期操作のオプション)。• 操作の種類 (上方または下方)。• 進行率 (整数、0 ~ 100)。• トランザクション内の総レコード数。

同期マネージャの使用同期マネージャオブジェクトは、単純な上位同期操作と下位同期操作を実行します。下位同期の場合、ユーザに代わって認証済み要求をサーバに送信し、応答データを SmartStore にローカルに保存します。上位同期の場合、指定したレコードを SmartStore から収集し、ユーザの指示に従って対応するサーバレコードとマージします。同期マネージャは、Salesforceユーザおよびコミュニティユーザの認証を処理する方法を把握しています。同期マネージャは、すべての SmartStore インスタンス (デフォルトの SmartStore、グローバル SmartStore、または名前付きインスタンス) にレコードを保存できます。同期マネージャクラスには、カスタマイズされた同期マネージャインスタンスを返すファクトリメソッドがあります。同期マネージャを使用するには、同期操作の要件に一致するインスタンスを作成します。各同期アクティビティの正しいタイプの同期マネージャを作成することが最も重要です。そのようにしないと、顧客にランタイム認証エラーが発生する可能性があります。インスタンスを作成したら、次のような一般的な同期マネージャ機能をコールするために使用できます。• 下位同期• 上位同期• 再同期同期マネージャは、SmartStore スープエントリおよび Salesforce レコードで次の 3 つの種別のアクションを実行できます。• 作成• 更新

249

ネイティブアプリケーションでの SmartSync の使用オフライン管理

• 削除カスタムターゲットを指定すると、同期マネージャはカスタムターゲットを使用して、任意の REST エンドポイントでデータを同期できます。

SyncManager のインスタンス化 (Android)

Android では、次の各シナリオで異なるファクトリメソッドを使用します。現在のユーザの場合:

public static synchronized SyncManager getInstance();

指定のユーザの場合:

public static synchronized SyncManagergetInstance(UserAccount account);

指定のコミュニティの指定のユーザの場合:

public static synchronized SyncManagergetInstance(UserAccount account, String communityId);

指定の SmartStore データベースを使用する指定のコミュニティの指定のユーザの場合:

public static synchronized SyncManagergetInstance(UserAccount account, String communityId, SmartStore smartStore);

SFSmartSyncSyncManager のインスタンス化 (iOS)

iOS では、アクセスおよび削除メソッドのペアを使用します。SFSmartSyncSyncManagerクラスで sharedInstance:

クラスメソッドをコールし、各シナリオの事前設定済み共有インスタンスにアクセスします。特定の使用事例の共有インスタンスの使用を終了する場合、対応する removeSharedInstance*:... メソッドで削除します。指定のユーザの場合:

+ (instancetype)sharedInstance:(SFUserAccount *)user;+ (void)removeSharedInstance:(SFUserAccount *)user;

特定の SmartStore データベースを使用する指定のユーザの場合:

+ (instancetype)sharedInstanceForUser:(SFUserAccount *)userstoreName:(NSString *)storeName;

+ (void)removeSharedInstanceForUser:(SFUserAccount *)userstoreName:(NSString *)storeName;

指定の SmartStore データベースの場合:

+ (instancetype)sharedInstanceForStore:(SFSmartStore *)store;+ (void)removeSharedInstanceForStore:(SFSmartStore *)store;

250

ネイティブアプリケーションでの SmartSync の使用オフライン管理

下位同期サーバからローカルの SmartSync スープに sObject をダウンロードするには、「下位同期」メソッドを使用します。• Android SyncManager メソッド:

public SyncState syncDown(SyncTarget target, String soupName,SyncUpdateCallback callback) throws JSONException;

public SyncState syncDown(SyncTarget target, SyncOptions options,String soupName, SyncUpdateCallback callback)throws JSONException;

• iOS SFSmartSyncSyncManager メソッド:

- (SFSyncState*)syncDownWithTarget:(SFSyncTarget*)target

soupName:(NSString*)soupNameupdateBlock:(SFSyncSyncManagerUpdateBlock)updateBlock;

- (SFSyncState*)syncDownWithTarget:(SFSyncTarget*)target

options:(SFSyncOptions*)optionssoupName:(NSString*)soupName

updateBlock:(SFSyncSyncManagerUpdateBlock)updateBlock;

「下位同期」メソッドの場合、ダウンロードする sObject のリストを指定するターゲットを定義します。明示的なリストを指定するには、Android では JSONObject、iOS では NSDictionaryを使用します。ただし、クエリ文字列でターゲットを定義することもできます。同期ターゲットクラスでは、SOSL、SOQL、または MRU クエリからターゲットオブジェクトを作成するためのファクトリメソッドが提供されます。ダウンロードされたデータを受信するSmartStoreスープの名前も指定します。このスープには、__local__という名前のインデックス付けされた文字列項目が必要です。Mobile SDK は、コールバックメソッドか、指定された更新ブロックを使用して同期操作の進行状況をレポートします。

マージモードoptions パラメータを使用すると、ローカルで変更されたレコードの処理を制御できます。次のいずれかの動作を選択できます。1. 変更されたローカルレコードを上書きし、ローカルの変更をすべて消去する。optionsパラメータを次の

値に設定します。• Android: SyncOptions.optionsForSyncDown(MergeMode.OVERWRITE)

• iOS: [SFSyncOptions newSyncOptionsForSyncDown:SFSyncStateMergeModeOverwrite]

2. すべてのローカルの変更とローカルで変更されたレコードを保持する。optionsパラメータを次の値に設定します。• Android: SyncOptions.optionsForSyncDown(MergeMode.LEAVE_IF_CHANGED)

• iOS: [SFSyncOptions newSyncOptionsForSyncDown:SFSyncStateMergeModeLeaveIfChanged])

251

ネイティブアプリケーションでの SmartSync の使用オフライン管理

重要: options パラメータを取らないバージョンの syncDown を使用する場合、キャッシュ内にある既存の sObject が上書きされる可能性があります。ローカルの変更を保持するには、下位同期を実行する前に必ず上位同期を実行してください。

例: Android:

SmartSyncExplorer ネイティブサンプルアプリケーションは、Contact レコードに SmartSync を使用する方法を示します。Android の場合、このサンプルでは Salesforce Contact レコードを Java オブジェクトとして表すContactObject クラスを定義します。Contact データを SmartStore スープと下位同期するために、syncDownContactsメソッドは ContactObjectインスタンスの情報で作成された SOQL クエリから同期ターゲットを作成します。次のスニペットでは、SOQLBuilder を使用しています。SOQLBuilder は、実際の SOQL文字列のように解釈できる形式で SOQL クエリを動的に指定しやすくする、SmartSync ファクトリクラスです。各SOQLBuilder プロパティ setter は、コール側オブジェクトから作成された新しい SOQLBuilder オブジェクトを返します。これにより、1 つの論理ステートメント内でメソッドコールをチェーニングできます。SOQL クエリのすべての部分を指定したら、 build() をコールして最終的な SOQL 文字列を作成します。private void syncDownContacts() {

smartStore.registerSoup(ContactListLoader.CONTACT_SOUP,CONTACTS_INDEX_SPEC);

try {final String soqlQuery = SOQLBuilder.

getInstanceWithFields(ContactObject.CONTACT_FIELDS).from(Constants.CONTACT).limit(ContactListLoader.LIMIT).build();

final SyncTarget target =SyncTarget.targetForSOQLSyncDown(soqlQuery);

syncMgr.syncDown(target,ContactListLoader.CONTACT_SOUP,new SyncUpdateCallback() {

@Overridepublic void onUpdate(SyncState sync) {

handleSyncUpdate(sync);}

});

} catch (JSONException e) {Log.e(TAG, "JSONException occurred while parsing", e);

}}

下位同期操作が成功した場合、つまり SyncState.isDone()が true の場合は、受信したデータが指定されたスープに取り込まれます。そのため、handleSyncUpdate()メソッドで行われているように、コールバックメソッドで必要なのは簡単な実装のみです。private void handleSyncUpdate(SyncState sync) {

if (Looper.myLooper() == null) {Looper.prepare();

}if (sync.isDone()) {

switch(sync.getType()) {case syncDown:

252

ネイティブアプリケーションでの SmartSync の使用オフライン管理

Toast.makeText(MainActivity.this,Sync down successful!",Toast.LENGTH_LONG).show();

break;case syncUp:

Toast.makeText(MainActivity.this,"Sync up successful!",Toast.LENGTH_LONG).show();

syncDownContacts();break;

default:break;

}}

}

iOS:

SmartSyncExplorer ネイティブサンプルアプリケーションは、Contact レコードに SmartSync を使用する方法を示します。iOS の場合、このサンプルでは Salesforce Contact レコードを Objective-C オブジェクトとして表すContactSObjectDataクラスを定義します。サンプルではまた、ContactSObjectDataクラスをサポートする次の複数のクラスも定義します。• ContactSObjectDataSpec

• SObjectData

• SObjectDataSpec

• SObjectDataFieldSpec

• SObjectDataManager

Contact データをSmartStoreスープと下位同期するために、SObjectDataManagerの refreshRemoteData

メソッドは SOQL 文字列を使用して SFSyncTarget オブジェクトを作成します。このクエリ文字列は、Contact オブジェクトの情報で作成されています。SFSmartSyncSyncManager のsyncDownWithTarget:soupName:updateBlock: メソッドは、このターゲットと、返されたデータを受信するスープの名前を取ります。このメソッドには、同期操作が成功または失敗したときにコールされる更新ブロックも必要です。- (void)refreshRemoteData {

if (![self.store soupExists:self.dataSpec.soupName]) {[self registerSoup];

}

NSString *soqlQuery =[NSString

stringWithFormat:@"SELECT %@ FROM %@ LIMIT %d",[self.dataSpec.fieldNames

componentsJoinedByString:@","],self.dataSpec.objectType,kSyncLimit];

SFSyncTarget *syncTarget =[SFSyncTarget newSyncTargetForSOQLSyncDown:soqlQuery];

__weak SObjectDataManager *weakSelf = self;[self.syncMgr

253

ネイティブアプリケーションでの SmartSync の使用オフライン管理

syncDownWithTarget:syncTargetsoupName:self.dataSpec.soupName

updateBlock:^(SFSyncState* sync) {if ([sync isDone] || [sync hasFailed]) {

[weakSelf refreshLocalData];}

}];

}

下位同期操作が成功した場合、つまり SFSyncState の isDone メソッドが YES を返した場合は、指定されたスープがサーバデータを受信します。次に、更新ブロックは制御を refreshLocalDataメソッドに渡し、このメソッドがデータをスープから取得し、変更を反映して UI を更新します。- (void)refreshLocalData {

if (![self.store soupExists:self.dataSpec.soupName]) {[self registerSoup];

}

SFQuerySpec *sobjectsQuerySpec =[SFQuerySpec

newAllQuerySpec:self.dataSpec.soupNamewithPath:self.dataSpec.orderByFieldNamewithOrder:kSFSoupQuerySortOrderAscending

withPageSize:kMaxQueryPageSize];NSError *queryError = nil;NSArray *queryResults =

[self.storequeryWithQuerySpec:sobjectsQuerySpec

pageIndex:0error:&queryError];

[self log:SFLogLevelDebugmsg:@"Got local query results. "

"Populating data rows."];if (queryError) {

[self log:SFLogLevelErrorformat:@"Error retrieving '%@' data "

"from SmartStore: %@",self.dataSpec.objectType,[queryError localizedDescription]];

return;}

self.fullDataRowList = [self populateDataRows:queryResults];[self log:SFLogLevelDebug

format:@"Finished generating data rows. ""Number of rows: %d. Refreshing view.",[self.fullDataRowList count]];

[self resetDataRows];}

254

ネイティブアプリケーションでの SmartSync の使用オフライン管理

増分下位同期特定のターゲット種別では、以前の下位同期操作を増分再同期できます。下位同期ターゲットで再同期がサポートされている場合、Mobile SDK は、新しいレコードまたは更新されたレコードのみを取得します。サポートされていない場合は、同期操作全体が再実行されます。組み込みの 3 つの下位同期ターゲット (MRU、SOSL ベース、および SOQL ベース) のうち、SOQL ベースの下位同期ターゲットでのみ再同期がサポートされています。カスタム同期ターゲットで再同期をサポートするには、取得操作中に渡される maxTimeStamp パラメータを使用します。Mobile SDK は、下位同期中にダウンロード済みのレコードからターゲットで指定された変更日付項目をチェックし、最新のタイムスタンプを判断します。その下位同期の再同期を要求する場合、Mobile SDK は最新のタイムスタンプ (利用可能な場合) を下位同期ターゲットに渡します。その後、下位同期ターゲットは、指定したタイムスタンプ以降に作成または更新されたレコードのみを取得します。デフォルトの変更日付項目はlastModifiedDate です。

制限事項増分同期後、次の未使用のレコードはローカルスープに保持されます。• 削除されたレコード• 下位同期ターゲットを満たさなくなったレコードこれらの孤立したレコードを削除する場合、次の操作を実行できます。• 完全下位同期操作を実行する• 完全下位同期操作で返される ID に対して、ローカルレコードの ID を比較する

再同期メソッドの呼び出しAndroid:

SyncManager インスタンスで、次をコールします。SyncState reSync(long syncId, SyncUpdateCallback callback);

iOS:

SFSmartSyncSyncManager インスタンスで、次をコールします。- (SFFSyncState*) reSync:(NSNumber *)syncId

updateBlock:(SFSyncSyncManagerUpdateBlock)updateBlock;

ハイブリッド:

次をコールします。cordova.require("com.salesforce.plugin.SmartSync").reSync(syncId,successCB);

サンプルアプリケーションAndroid

SmartSyncExplorer サンプルアプリケーションは、ContactListLoader クラスで reSync() を使用します。iOS

SmartSyncExplorer サンプルアプリケーションは、SObjectDataManagerクラスで reSync()を使用します。

255

ネイティブアプリケーションでの SmartSync の使用オフライン管理

ハイブリッドSimpleSync サンプルアプリケーションは、SimpleSync.htmlの app.views.SearchPageクラスで reSync()

を使用します。

上位同期ローカルの変更をサーバに適用するには、次のいずれかの「上位同期」メソッドを使用します。• Android SyncManager メソッド:

public SyncState syncUp(SyncOptions options, String soupName,SyncUpdateCallback callback) throws JSONException

• iOS SFSmartSyncSyncManager メソッド:

- (SFSyncState*)syncUpWithOptions:(SFSyncOptions*)options

soupName:(NSString*)soupNameupdateBlock:(SFSyncSyncManagerUpdateBlock)updateBlock;

これらのメソッドはサーバを特定の SmartStore スープのデータで更新します。スープ内にある作成、更新、または削除されたレコードが検索され、それらの変更がサーバ上で複製されます。options 引数には更新する項目のリストを指定します。ローカルに作成されたオブジェクトには、sObject の型を指定する「type」項目を含む「attributes」項目を含める必要があります。たとえば、Acme という名前の取引先の場合、{Id:”local_x”, Name: Acme, attributes:

{type:”Account”}} を使用します。

マージモード上位同期操作の場合、mergeMode オプションを指定できます。次のいずれかの動作を選択できます。1. サーバレコードが該当のクライアントに下位同期してから変更された場合でも、サーバレコードを上書き

します。syncUp メソッドをコールすると、次のようになります。• Android: options パラメータが SSyncOptions.optionsForSyncUp(fieldlist,

SyncState.MergeMode.OVERWRITE) に設定される• iOS: options パラメータが [SFSyncOptions newSyncOptionsForSyncUp:fieldlist

mergeMode:SFSyncStateMergeModeOverwrite] に設定される• ハイブリッド: syncOptions パラメータが {mergeMode:"OVERWRITE"} に設定される

2. サーバレコードが該当のクライアントに下位同期してから変更された場合、現在の状態のまま保持されます。対応するクライアントレコードも現在の状態のまま保持されます。syncUp() メソッドをコールすると、次のようになります。• Android: options パラメータが SyncOptions.optionsForSyncUp(fieldlist,

SyncState.MergeMode.LEAVE_IF_CHANGED) に設定される• iOS: options パラメータが [SFSyncOptions newSyncOptionsForSyncUp:fieldlist

mergeMode:SFSyncStateMergeModeLeaveIfChanged] に設定される• ハイブリッド: syncOptions パラメータが {mergeMode:"LEAVE_IF_CHANGED"} に設定される

256

ネイティブアプリケーションでの SmartSync の使用オフライン管理

ローカルレコードにターゲットの変更日付項目が含まれている場合、Mobile SDK は、その項目とサーバレコードの対応項目を比較して変更を検出します。デフォルトの変更日付項目は lastModifiedDateです。ローカルレコードに変更日付項目が含まれていない場合、LEAVE_IF_CHANGED 上位同期操作が上書きモードの上位同期に戻ります。

重要: LEAVE_IF_CHANGED マージでは、サーバへの追加の往復処理が必要になります。さらに重要なのは、状況チェック操作とレコード保存操作が連続した 2 つのコールで発生することです。まれに、これらのコールの間に更新されるレコードがサーバで時期尚早に変更される場合があります。

例: Android:

サーバに上位同期する場合は、syncDown()と同じ引数 (項目のリスト、ソースSmartStoreスープの名前、更新コールバック) を指定して syncUp()をコールします。コーディング上の違いは、影響を受ける項目のリストを SyncTargetではなく SyncOptionsのインスタンスとして形式設定する点のみです。次に、SmartSyncExplorer サンプルでのその処理方法を示します。private void syncUpContacts() {

final SyncOptions options =SyncOptions.optionsForSyncUp(Arrays.asList(ContactObject.CONTACT_FIELDS));

try {syncMgr.syncUp(options, ContactListLoader.CONTACT_SOUP,

new SyncUpdateCallback() {@Overridepublic void onUpdate(SyncState sync) {

handleSyncUpdate(sync);}

});} catch (JSONException e) {

Log.e(TAG, "JSONException occurred while parsing", e);}

}

SmartSyncExplorer の例の場合、更新コールバックでは上位同期が完了すると syncDownContacts()をコールするという追加のステップを実行します。このステップにより、SmartStore スープにサーバでの Contact

への最近の変更がすべて反映され、最新の状態であることが保証されます。private void handleSyncUpdate(SyncState sync) {

if (Looper.myLooper() == null) {Looper.prepare();

}if (sync.isDone()) {

switch(sync.getType()) {case syncDown:

Toast.makeText(MainActivity.this,Sync down successful!",Toast.LENGTH_LONG).show();

break;case syncUp:

Toast.makeText(MainActivity.this,"Sync up successful!",Toast.LENGTH_LONG).show();

257

ネイティブアプリケーションでの SmartSync の使用オフライン管理

syncDownContacts();break;

default:break;

}}

}

iOS:

サーバに上位同期する場合は、下位同期に使用したものと同じ引数 (項目のリスト、ソースSmartStoreスープの名前、更新ブロック) を指定して syncUp:withOptions:soupName:updateBlock: メッセージをSFSmartSyncSyncManager に送信します。コーディング上の違いは、影響を受ける項目のリストをSFSyncTargetではなく SFSyncOptionsのインスタンスとして形式設定する点のみです。SmartSyncExplorer

サンプルが上位同期メッセージを送信する方法を次に示します。- (void)updateRemoteData:

(SFSyncSyncManagerUpdateBlock)completionBlock {

SFSyncOptions *syncOptions =[SFSyncOptions newSyncOptionsForSyncUp:

self.dataSpec.fieldNames];[self.syncMgr syncUpWithOptions:syncOptions

soupName:self.dataSpec.soupNameupdateBlock:^(SFSyncState* sync) {

if ([sync isDone] || [sync hasFailed]) {completionBlock(sync);

}}

];}

ここに示す更新ブロックは、同期操作が完了したと判断すると、updateRemoteData に渡される完了ブロックをコールします。ユーザは、ボタンをタップして同期操作を開始します。したがって、完了ブロックの定義を確認するには、ContactListViewController.m の syncUpDown ボタンハンドラを調べます。このハンドラは次のブロックで updateRemoteData をコールします。[self.dataMgr updateRemoteData:^(SFSyncState *syncProgressDetails){

dispatch_async(dispatch_get_main_queue(), ^{weakSelf.navigationItem.rightBarButtonItem.enabled = YES;if ([syncProgressDetails isDone]) {

[weakSelf.dataMgr refreshLocalData];[weakSelf showToast:@"Sync complete!"];[weakSelf.dataMgr refreshRemoteData];

} else if ([syncProgressDetails hasFailed]) {[weakSelf showToast:@"Sync failed."];

} else {[weakSelf showToast:[NSString

stringWithFormat:@"Unexpected status: %@",[SFSyncState syncStatusToString:

syncProgressDetails.status]]

];

258

ネイティブアプリケーションでの SmartSync の使用オフライン管理

}});

}];

上位同期操作が成功すると、このブロックは最初にデバイスの表示を更新して「Sync complete!」(同期完了) という確認トーストを表示してから、SObjectDataManager メッセージを refreshRemoteData に送信します。この最終ステップにより、SmartStore スープにサーバでの Contact への最近の変更がすべて反映され、最新の状態であることが保証されます。

下位同期操作後の「ゴースト」レコードの処理下位同期操作で SmartStoreスープに不要なレコードが残ることがある場合、cleanResyncGhosts API を使用して削除できます。規定された特定のケースでは、最新の下位同期操作のコンテンツがSmartStoreスープに正確に反映されません。たとえば、Salesforce サーバでレコードが削除されても、次の下位同期操作で SmartStore からそのレコードが削除されません。また、同期条件を満たしていないレコードが下位同期結果から除外されても、自動的にスープから削除されません。SmartStoreスープに予期せず残るこれらのレコードは、ゴーストレコードと呼ばれます。Mobile SDK 4.2 では、ゴーストレコードを識別して削除する cleanResyncGhosts メソッドが SmartSync に追加されています。このメソッドは、Android ネイティブ、iOS ネイティブ、ハイブリッド、React Native プラットフォームで使用できます。

警告: 練習では、cleanResyncGhostsメソッドの使用に制限があります。このメソッドへのコールは、ランタイムパフォーマンスとペイロードサイズの両方でコストかかる可能性があります。このメソッドは、各下位同期操作の一部としてではなく、頻度の低いクリーンアップ操作として使用します。

Android ネイティブpublic void cleanResyncGhosts(long syncId)

iOS ネイティブ- (void)

cleanResyncGhosts:(NSNumber*)syncIdcompletionStatusBlock:(SFSyncSyncManagerCompletionStatusBlock)completionStatusBlock

ハイブリッドvar cleanResyncGhosts = function(isGlobalStore, syncId, successCB, errorCB)

React Native

smartsync.cleanResyncGhosts(isGlobalStore, syncId, successCB, errorCB)

カスタム下位同期ターゲットと cleanResyncGhosts の併用アプリケーションでカスタム下位同期ターゲットを使用する場合、cleanResyncGhosts でgetListOfRemoteIdsメソッドを実装するカスタムターゲットが必要になります。このメソッドは、下位同期ターゲットの条件を満たす Salesforce ID のリストを返します。getListOfRemoteIds のコード例については、次のSmartSyncライブラリフォルダで SOQL、SOSL、または MRU の下位同期ターゲットを確認してください。

259

ネイティブアプリケーションでの SmartSync の使用オフライン管理

iOShttps://github.com/forcedotcom/SalesforceMobileSDK-iOS/tree/master/libs/SmartSync/SmartSync/Classes/Util

Androidhttps://github.com/forcedotcom/SalesforceMobileSDK-Android/tree/master/libs/SmartSync/src/com/salesforce/androidsdk/smartsync/util

グローバル SmartStore での同期マネージャの使用グローバル SmartStoreインスタンスで SmartSyncを使用するには、同期マネージャオブジェクトで静的ファクトリメソッドをコールして、互換性のある同期マネージャインスタンスを取得します。Android:

説明静的メソッド

指定したコミュニティユーザとしてサーバと通信し、特定の SmartStore インスタンスに対する読み書

SyncManager getInstance(UserAccountaccount, String communityId, SmartStoresmartStore); きを行う同期マネージャインスタンスを返します。

このファクトリメソッドを使用して、グローバルSmartStore インスタンスとデータを同期します。

指定したコミュニティユーザとしてサーバと通信し、ユーザのデフォルトの SmartStore インスタンス

SyncManager getInstance(UserAccountaccount, String communityId);

に対する読み書きを行う同期マネージャインスタンスを返します。

指定したユーザとしてサーバと通信し、ユーザのデフォルトの SmartStore インスタンスに対する読み書きを行う同期マネージャインスタンスを返します。

SyncManager getInstance(UserAccountaccount);

現在のユーザとしてサーバと通信し、現在のユーザのデフォルトの SmartStore インスタンスに対する読

SyncManager getInstance();

み書きを行う同期マネージャインスタンスを返します。

iOS:

説明静的メソッド

指定したユーザとしてサーバと通信し、ユーザのデフォルトの SmartStore インス

+ (instancetype)sharedInstanceForUser:

タンスに対する読み書きを行う同期マネージャインスタンスを返します。

(SFUserAccount *)userstoreName:

(NSString *)storeName;

現在のユーザとしてサーバと通信し、特定の SmartStore インスタンスに対する読

+ (instancetype)sharedInstanceForStore:

(SFSmartStore *)store; み書きを行う同期マネージャインスタン

260

ネイティブアプリケーションでの SmartSync の使用オフライン管理

説明静的メソッド

スを返します。このファクトリメソッドを使用して、グローバル SmartStore インスタンスとデータを同期します。

指定したユーザとしてサーバと通信し、ユーザのデフォルトの SmartStore インス

+ (instancetype)sharedInstance:

(SFUserAccount *)user; タンスに対する読み書きを行う同期マネージャインスタンスを返します。

ハイブリッド:

次の各メソッドの省略可能な isGlobalStoreパラメータでは、グローバルSmartStoreインスタンスを使用するかどうかを SmartSync プラグインに通知します。isGlobalStore が true の場合、SmartSync はデフォルトのグローバル SmartStore インスタンスに対する読み書きを行います。isGlobalStore が false の場合、またはパラメータを省略した場合、SmartSyncは現在のユーザのデフォルトのSmartStoreインスタンスに対する読み書きを行います。• syncDown(isGlobalStore, target, soupName, options, successCB, errorCB);

• reSync(isGlobalStore, syncId, successCB, errorCB);

• syncUp(isGlobalStore, target, soupName, options, successCB, errorCB);

• getSyncStatus(isGlobalStore, syncId, successCB, errorCB);

カスタム下位同期ターゲットの使用下位同期操作中、下位同期ターゲットを使用して、ダウンロードするレコードセットや要求エンドポイントを制御します。事前書式設定済みの MRU ターゲット、SOQL ベースターゲット、および SOSL ベースターゲットを使用できます。または、カスタム下位同期ターゲットを作成することもできます。カスタムターゲットでは、Salesforce 内外の任意の REST エンドポイントにアクセスできます。

カスタム下位同期ターゲットの定義下位同期ターゲットのプラットフォームの抽象基本クラスをサブクラス化して、下位同期操作のカスタムターゲットを定義します。ハイブリッドアプリケーションでカスタムターゲットを使用するには、サポートされている各プラットフォームのカスタムネイティブターゲットクラスを実装します。下位同期ターゲットの基本クラスは次のとおりです。• Android: SyncDownTarget

• iOS: SFSyncDownTarget

各カスタムターゲットクラスでは、次の必須メソッドを実装する必要があります。

261

ネイティブアプリケーションでの SmartSync の使用オフライン管理

Start Fetch メソッド下位同期操作を開始するために同期マネージャによってコールされます。maxTimeStamp が 0 より大きい場合、この操作は「再同期」になります。その後、指定した時間以降に作成または更新されたレコードのみが返されます。Android:

JSONArray startFetch(SyncManager syncManager, long maxTimeStamp);

iOS:

- (void) startFetch:(SFSmartSyncSyncManager*)syncManagermaxTimeStamp:(long long)maxTimeStamperrorBlock:(SFSyncDownTargetFetchErrorBlock)

errorBlockcompleteBlock:(SFSyncDownTargetFetchCompleteBlock)

completeBlock;

Continue Fetching メソッドメソッドで null が返されるまで同期マネージャによって繰り返しコールされます。このプロセスでは、同期が必要なすべてのレコードが取得されます。Android:

JSONArray continueFetch(SyncManager syncManager);

iOS:

- (void)continueFetch:(SFSmartSyncSyncManager*)syncManager

errorBlock:(SFSyncDownTargetFetchErrorBlock)errorBlock

completeBlock:(SFSyncDownTargetFetchCompleteBlock)completeBlock;

modificationDateFieldName プロパティ (省略可能)

必要に応じて、カスタムクラスで modificationDateFieldName プロパティを上書きできます。Mobile

SDK では、この名前の項目を使用して、下位同期操作を再実行するために startFetch で使用されるmaxTimestamp の値を計算します。この操作は再同期とも呼ばれます。デフォルトの項目はlastModifiedDate です。Android:

String getModificationDateFieldName();

iOS:

modificationDateFieldName プロパティidFieldName プロパティ (省略可能)

必要に応じて、カスタムクラスで idFieldName プロパティを上書きできます。Mobile SDKでは、この名前の項目を使用して、レコードの ID を取得します。たとえば、Mobile SDKは、上位同期中に updateOnServer()

メソッドに渡す ID をローカルレコードの idFieldName と名前が一致する項目から取得します。Android:

String getIdFieldName();

iOS:

idFieldName プロパティ

262

ネイティブアプリケーションでの SmartSync の使用オフライン管理

カスタムターゲットでの下位同期メソッドの呼び出しAndroid:

カスタム SyncDownTarget クラスのインスタンスを SyncManager 下位同期メソッドに渡します。SyncState syncDown(SyncDownTarget target, SyncOptions options, String soupName,SyncUpdateCallback callback);

iOS:

カスタム SFSyncDownTarget クラスのインスタンスを SFSmartSyncSyncManager 下位同期メソッドに渡します。- (SFSyncState*)

syncDownWithTarget:(SFSyncDownTarget*)targetsoupName:(NSString*)soupName

updateBlock:(SFSyncSyncManagerUpdateBlock)updateBlock;

ハイブリッド:

1. 次のプロパティ設定を使用してターゲットオブジェクトを作成します。• type を「custom」に設定する。• 少なくとも次のいずれかのプロパティを設定する。

Android (サポートされている場合):

Android カスタムクラスのパッケージ修飾名に androidImpl を設定します。iOS (サポートされている場合):

iOS カスタムクラスの名前に iOSImpl を設定します。

次の例は、Android と iOS の両方に対応しています。var target ={type:"custom",androidImpl:"com.salesforce.samples.notesync.ContentSoqlSyncDownTarget",iOSImpl:"SFContentSoqlSyncDownTarget",…};

2. このターゲットをハイブリッド下位同期メソッドに渡します。cordova.require("com.salesforce.plugin.SmartSync").syncDown(target, …);

サンプルアプリケーションAndroid

NoteSync ネイティブ Android サンプルアプリケーションは、com.salesforce.samples.notesync.ContentSoqlSyncDownTarget 下位同期ターゲットを定義および使用します。

263

ネイティブアプリケーションでの SmartSync の使用オフライン管理

iOS

NoteSync ネイティブ iOS サンプルアプリケーションは、SFContentSoqlSyncDownTarget下位同期ターゲットを定義および使用します。

カスタム上位同期ターゲットの使用上位同期操作中、上位同期ターゲットを使用して、アップロードするレコードセットや、サーバのレコードを更新する REST エンドポイントを制御します。カスタム上位同期ターゲットを作成して、Salesforce内外の任意のREST エンドポイントにアクセスできます。

カスタム上位同期ターゲットの定義上位同期ターゲットのプラットフォームの抽象基本クラスをサブクラス化して、上位同期操作のカスタムターゲットを定義します。ハイブリッドアプリケーションでカスタムターゲットを使用するには、サポートされている各プラットフォームのカスタムネイティブターゲットクラスを実装する必要があります。上位同期ターゲットの基本クラスは次のとおりです。• Android: SyncUpTarget

• iOS: SFSyncUpTarget

各カスタムターゲットクラスでは、次の必須メソッドを実装する必要があります。Create On Server メソッド

ローカルで作成されたレコードを上位同期します。Android:

String createOnServer(SyncManager syncManager,String objectType, Map<String, Object> fields);

iOS:

- (void) createOnServer:(NSString*)objectTypefields:(NSDictionary*)fields

completionBlock:(SFSyncUpTargetCompleteBlock)completionBlock

failBlock:(SFSyncUpTargetErrorBlock)failBlock;

Update On Server メソッドローカルで更新されたレコードを上位同期します。objectId パラメータの場合、SmartSync は、カスタムターゲットの getIdFieldName() メソッド (Android) または idFieldName プロパティ (iOS) で指定された項目を使用します。Android:

updateOnServer(SyncManager syncManager, String objectType, String objectId,Map<String, Object> fields);

iOS:

- (void) updateOnServer:(NSString*)objectTypeobjectId:(NSString*)objectIdfields:(NSDictionary*)fields

completionBlock:(SFSyncUpTargetCompleteBlock)

264

ネイティブアプリケーションでの SmartSync の使用オフライン管理

completionBlockfailBlock:(SFSyncUpTargetErrorBlock)failBlock;

Delete On Server メソッドローカルで削除されたレコードを上位同期します。objectId パラメータの場合、SmartSync は、カスタムターゲットの getIdFieldName() メソッド (Android) または idFieldName プロパティ (iOS) で指定された項目を使用します。Android:

deleteOnServer(SyncManager syncManager, String objectType,String objectId);

iOS:

- (void) deleteOnServer:(NSString*)objectTypeobjectId:(NSString*)objectId

completionBlock:(SFSyncUpTargetCompleteBlock)completionBlock

failBlock:(SFSyncUpTargetErrorBlock)failBlock;

省略可能な設定の変更必要に応じて、カスタムクラスで次の値を上書きできます。getIdsOfRecordsToSyncUp

上位同期で返されるレコード ID のリスト。デフォルトでは、これらのメソッドで __local__ が true のすべてのレコードが返されます。

Android:

Set<String> getIdsOfRecordsToSyncUp(SyncManager syncManager,String soupName);

iOS:

- (NSArray*)getIdsOfRecordsToSyncUp:(SFSmartSyncSyncManager*)syncManager

soupName:(NSString*)soupName;

変更日付項目名レコードがリモートで変更されたかどうかを判断するために LEAVE_IF_CHANGED 上位同期操作中に使用される項目。デフォルト値は lastModifiedDate です。

Android:

String getModificationDateFieldName();

iOS:

modificationDateFieldName プロパティ最終変更日付

レコードで返される最終変更日付値。デフォルトでは、同期ターゲットはレコードの変更日付項目値を取得します。

265

ネイティブアプリケーションでの SmartSync の使用オフライン管理

Android:

String fetchLastModifiedDate(SyncManager syncManager,String objectType, String objectId);

iOS:

- (void)fetchRecordModificationDates:(NSDictionary *)record

modificationResultBlock:(SFSyncUpRecordModificationResultBlock)modificationResultBlock

ID 項目名レコードの ID を取得するために使用される項目。たとえば、Mobile SDK は、上位同期中にupdateOnServer() メソッドに渡す ID をローカルレコードの idFieldName と名前が一致する項目から取得します。Android:

String getIdFieldName();

iOS:

idFieldName プロパティ

カスタムターゲットでの上位同期メソッドの呼び出しAndroid:

SyncManager インスタンスで、次をコールします。SyncState syncUp(SyncUpTarget target,

SyncOptions options, String soupName,SyncUpdateCallback callback);

iOS:

SFSyncManager インスタンスで、次をコールします。

- (SFSyncState*)syncUpWithOptions:(SFSyncOptions*)options

soupName:(NSString*)soupNameupdateBlock:(SFSyncSyncManagerUpdateBlock)updateBlock

ハイブリッド:

cordova.require("com.salesforce.plugin.smartsync").syncUp(isGlobalStore, target, soupName,

options, successCB, errorCB);

キャッシュデータの保存および取得キャッシュマネージャは、SmartSync キャッシュとの間で sObject メタデータの書き込みおよび読み取りを行うメソッドを提供します。どのメソッドも、キャッシュ内のデータを識別するキー文字列を指定する必要があります。アプリケーションがキャッシュデータの位置を特定するために役立つ、任意の一意の文字列を使用できます。

266

ネイティブアプリケーションでの SmartSync の使用オフライン管理

また、キャッシュデータのタイプも指定します。キャッシュマネージャのメソッドは、sObject データの 3 つのカテゴリ (メタデータ、MRU (最近使用した) リスト、レイアウト) のいずれかの読み取りおよび書き込みを行います。指定したタイプ識別子は各自のアプリケーションでしか使用されないため、これらのデータタイプを明確に区別する一意の文字列を使用できます。

キャッシュマネージャのクラス• Android: com.salesforce.androidsdk.smartsync.manager.CacheManager

• iOS: SFSmartSyncCacheManager

読み取りおよび書き込みメソッドsObject メタデータ、MRU リスト、sObject レイアウトの読み取りおよび書き込みを行う CacheManagerのメソッドを次に示します。• Android:

sObject メタデータpublic List<SalesforceObject> readObjects(String cacheType,

String cacheKey);public void writeObjects(List<SalesforceObject> objects,

String cacheKey, String cacheType);

MRU リストpublic List<SalesforceObjectType>readObjectTypes(String cacheType, String cacheKey);

public voidwriteObjectTypes(List<SalesforceObjectType> objects,

String cacheKey, String cacheType);

sObject レイアウトpublic List<SalesforceObjectTypeLayout>readObjectLayouts(String cacheType, String cacheKey);

public voidwriteObjectLayouts(List<SalesforceObjectTypeLayout> objects,

String cacheKey, String cacheType);

• iOS:

Read メソッド- (NSArray *)readDataWithCacheType:(NSString *)cacheType

cacheKey:(NSString *)cacheKeycachePolicy:(SFDataCachePolicy)cachePolicyobjectClass:(Class)objectClasscachedTime:(out NSDate **)lastCachedTime;

267

ネイティブアプリケーションでの SmartSync の使用オフライン管理

Write メソッド- (void)writeDataToCache:(id)data

cacheType:(NSString *)cacheTypecacheKey:(NSString *)cacheKey;

キャッシュのクリアアプリケーションのキャッシュをクリアする準備ができたら、キャッシュマネージャの次のメソッドを使用します。• Android:

public void removeCache(String cacheType, String cacheKey);

• iOS:

- (void)removeCache:(NSString *)cacheTypecacheKey:(NSString *)cacheKey;

これらのメソッドにより、キャッシュの選択した部分がクリアされます。キャッシュ全体をクリアするには、保存している各キャッシュキーおよびデータ型に対するメソッドをコールします。

ハイブリッドアプリケーションでの SmartSync の使用ハイブリッドアプリケーション用の SmartSync Data Framework は、Salesforce オブジェクトを JavaScript オブジェクトとして表す Mobile SDK ライブラリです。ハイブリッドアプリケーションで SmartSync を使用すると、Salesforce

オブジェクトのモデルを作成でき、そのモデルのデータを変更するだけで基盤となるレコードを操作できます。SOQL または SOSL クエリを実行すると、JSON 文字列としてではなくモデルコレクションで結果レコードが取得されます。Mobile SDK では、ハイブリッドアプリケーションで SmartSync を使用するために 2 つのオプションがあります。• com.salesforce.plugin.smartsync: SmartSync プラグインは基本的な「上位同期」と「下位同期」機能

を提供します。このプラグインは、ネイティブ SmartSyncライブラリの一部を公開します。単純な同期タスクの場合、プラグインを使用して、Web ビューではなくネイティブスレッドでレコードを迅速に同期できます。

• smartsync.js: SmartSync JavaScript ライブラリは、より複雑な同期操作のための Force.SObject データフレームワークを提供します。このライブラリは、拡張性の高いデータモデリングメカニズムを定義するオープンソースの JavaScript フレームワークである backbone.jsをベースにしています。この技術を理解するには、backbonejs.org にある例とドキュメントを参照してください。

SmartSync の使用方法を示す一連のサンプルハイブリッドアプリケーションが次の場所に用意されています。hybrid/SampleApps/AccountEditor/assets/wwwフォルダのサンプルアプリケーションは、smartsync.js

での Force.SObject ライブラリの使用方法を示します。• Account Editor (AccountEditor.html)

• User Search (UserSearch.html)

• User and Group Search (UserAndGroupSearch.html)

268

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

hybrid/SampleApps/SimpleSync フォルダのサンプルアプリケーションは、SmartSync プラグインの使用方法を示します。

Smartsync.js と SmartSync プラグインのどちらを使用すべきですか?SmartSync の JavaScript バージョンである Smartsync.js と、Cordova プラグインを介してハイブリッドアプリケーションで使用できるネイティブ SmartSync は、同じ名前ですがその利点は異なります。smartsync.js は、backbone.js 上に構築され、1 つまたは一連のレコードを表す使いやすいモデルオブジェクトを提供します。また、便利な取得、保存、および削除メソッドも提供します。ただし、完全な上位同期または下位同期機能はありません。SObjectCollection でのレコードの取得はプラグインの syncDownメソッドに似ていますが、取得されたすべてのオブジェクトはメモリ内に格納されます。そのため、大量のデータセットを移動する場合には適していません。さらに、上位同期機能を自分で実装する必要があります。AccountEditor サンプルアプリケーションは、一般的な JavaScript syncUp() の実装を示します。ネイティブ SmartSync は、モデルオブジェクトを返しませんが、サーバとの間で大量のデータセットを移動するための堅牢な syncUp および syncDown メソッドを提供します。また、2 つのライブラリを一緒に使用することもできます。たとえば、smartsync.jsで Force.StoreCache

を設定して、SmartSync プラグインを使用してデータを同期し、smartsync.js を使用して取得または保存をコールできます。その後、SmartSync プラグインを使用して同じキャッシュから上位同期できます。これにより、すべてが機能するようになります。両方のライブラリで独自のカスタムエンドポイントを定義できます。どちらを選択しますか? この決定をする場合、次のガイドラインが役立ちます。• JavaScript でデータを保存または取得するためにサーバと直接通信する場合、smartsync.js のカスタムエ

ンドポイントを使用します。• SmartStoreとのみ通信し、SmartSyncプラグインを使用してSmartStoreにデータを取り込む場合、smartsync.js

のカスタムエンドポイントは必要ありません。ただし、ネイティブカスタムターゲットを定義する必要があります。

Backbone テクノロジについてSmartSync ライブラリ smartsync.js は、オープンソースの Backbone JavaScript ライブラリの拡張機能を提供します。Backbone ライブラリは、Web アプリケーションを構築する主要なビルディングブロックを定義します。• 情報をモデル化する Models (キーと値のバインドイベントおよびカスタムイベントを含む)

• データセットを格納する Collections (豊富な enumerable 関数の API を含む)

• モデルの情報を表示する Views (宣言型イベント処理を含む)

• ビュー間の移動を制御するルータSalesforce SmartSync Data Frameworkは、Modelおよび Collectionコア Backbone オブジェクトを拡張し、Salesforce

REST API に接続します。SmartSync は、SmartStore (Mobile SDK の安全なストレージコンポーネント) を介してオフラインサポート (省略可能) も提供します。Backbone についての詳細は、http://backbonejs.org/ および http://backbonetutorials.com/ を参照してください。また、オンラインで「backbone javascript」を検索すれば、多数のチュートリアルやビデオを見つけることもできます。

269

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

モデルとモデルコレクションSmartSync Data Framework は、次の 2 つの種別のオブジェクトで構成されています。• モデル• モデルコレクションこれらのオブジェクトの定義は、backbone.js (一般的なサードパーティの JavaScript フレームワーク) で定義されているクラスを拡張します。背景情報は、「モデルとモデルコレクション」を参照してください。

モデルクライアントのモデルはサーバレコードを表します。SmartSyncでは、モデルオブジェクトは Force.SObject

(Backbone.Model クラスのサブクラス) のインスタンスです。SObject は、Salesforce API および SmartStore (必要に応じて) と連動するように Model を拡張します。SObject モデルオブジェクトで次の CRUD 操作を実行できます。• Create

• Destroy

• Fetch

• Save

• Get/set attributes

また、モデルオブジェクトは監視可能です。ビューとコントローラはオブジェクトの変更時に通知を受信できます。

プロパティForce.SObject は、次のプロパティを Backbone.Model に追加します。sobjectType

必須。このモデルが表す Salesforce オブジェクトの名前。この値は、標準オブジェクトまたはカスタムオブジェクトのいずれかを参照できます。

fieldlist

必須。取得、保存、破棄する項目の名前。cacheMode

オフラインの動作。mergeMode

競合処理の動作。cache

更新可能なレコードのオフラインストレージの場合に使用します。SmartSync Data Framework には、Force.StoreCache (SmartStore によってサポートされるキャッシュ実装) が組み込まれています。

cacheForOriginals

競合検出に対応できるように、サーバから取得したレコードの元のコピーを格納します。

270

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

例モデルプロパティの値は、次のような複数の方法で割り当てることができます。• Force.SObject インスタンスのプロパティとして割り当てる。• Force.SObject サブクラスのメソッドとして割り当てる。これらのメソッドでは、目的の CRUD アクショ

ン (「create」、「create」、「update」、「delete」) を指定するパラメータを使用します。• fetch()、save()、destroy() 関数コールのパラメータで割り当てる。たとえば、次のコードスニペットはどれも同じ内容になります。// As properties on a Force.SObject instanceacc = new Force.SObject({Id:"<some_id>"});acc.sobjectType = "account";acc.fieldlist = ["Id", "Name"];acc.fetch();

// As methods on a Force.SObject sub-classAccount = Force.SObject.extend({sobjectType: "account",fieldlist: function(method) { return ["Id", "Name"];}

});Acc = new Account({Id:"<some_id>"});acc.fetch();

// In the options parameter of fetch()acc = new Force.SObject({Id:"<some_id>"});acc.sobjectType = "account";acc.fetch({fieldlist:["Id", "Name"]);

モデルコレクションSmartSync Data Framework のモデルコレクションは、クエリ結果のコンテナです。モデルコレクションに保存されるクエリ結果は、SOQL、SOSL、MRU クエリを介してサーバから取得できます。また、必要に応じて、SmartSQL

(キャッシュがSmartStoreの場合) や別のクエリメカニズム (代替キャッシュを使用している場合) を介してキャッシュから取得することもできます。モデルコレクションオブジェクトは、Force.SObjectCollection (Backbone.Collectionクラスのサブクラス) のインスタンスです。SObjectCollection は、Salesforce API および SmartStore (必要に応じて) と連動するように Collection を拡張します。

プロパティForce.SObjectCollection は、次のプロパティを Backbone.Collection に追加します。config

必須。コレクションで保持できるレコードを定義します (SOQL、SOSL、MRU、SmartSQL を使用)。cache

更新可能なレコードのオフラインストレージの場合に使用します。SmartSync Data Framework には、Force.StoreCache (SmartStore によってサポートされるキャッシュ実装) が組み込まれています。

271

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

cacheForOriginals

競合検出に対応できるように、サーバから取得したレコードの元のコピーを格納します。

例モデルコレクションプロパティの値は、次のような複数の方法で割り当てることができます。• Force.SObject インスタンスのプロパティとして割り当てる• Force.SObject サブクラスのメソッドとして割り当てる• fetch()、save()、destroy() 関数コールのオプションパラメータで割り当てるたとえば、次のコードスニペットはどれも同じ内容になります。// As properties on a Force.SObject instancelist = new Force.SObjectCollection({config:<valid_config>});list.fetch();

// As methods on a Force.SObject sub-classMyCollection = Force.SObjectCollection.extend({config: function() { return <valid_config>; }

});list = new MyCollection();list.fetch();

// In the options parameter of fetch()list = new Force.SObjectCollection();list.fetch({config:valid_config});

SmartSync プラグインの使用Mobile SDK 3.0 以降の SmartSync プラグインは、SmartSync ネイティブライブラリの「上位同期」および「下位同期」機能への JavaScript アクセスを提供します。そのため、パフォーマンス集約的な操作 (ネットワークネゴシエーション、解析、SmartStore 管理など) はネイティブスレッド上で実行され、Web 表示操作に影響を与えません。SmartSync プラグインは、Mobile SDK の npm スクリプトによってハイブリッドプロジェクトに追加されます。• forceios バージョン 3.0 以降の場合、プラグインは自動的に含まれます。• forcedroid バージョン 3.0 以降の場合、SmartStore を使用するときは「yes」と回答します。SmartSync プラグインを既存のハイブリッドアプリケーションに追加する場合、forcedroid または forceios の最新バージョンを使用してアプリケーションを再作成することをお勧めします。新しいアプリケーションの準備ができたら、カスタム HTML、CSS、および JavaScript ファイルを古いプロジェクトから新しいプロジェクトにコピーします。

SmartSync プラグインのメソッドSmartSync プラグインは、syncDown() と syncUp() の 2 つのメソッドを公開します。これらのメソッドを使用する場合、いくつかの重要なガイドラインに従うと作業が簡素化されます。

272

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

• プラグインを使用して同期するレコードをローカルで作成、更新、または削除するには、smartsync.js

の Force.SObject を使用します。SmartSyncは、smartsync.js によって作成されるスープレコードにいくつかの特殊な項目があるものと想定します。

• 同様に、同期操作で使用するスープを作成するには、smartsync.js の Force.StoreCache を使用します。

• スープのオブジェクトを変更している場合は、syncDown() をコールする前に必ず syncUp() をコールします。

syncDown() メソッドtargetで指定した sObject を、soupNameで指定したSmartStoreスープにダウンロードします。スープの sObject

の ID がターゲットで指定したオブジェクトの ID と同じ場合は、SmartSync がスープの重複オブジェクトを上書きします。構文cordova.require("com.salesforce.plugin.smartsync").syncDown(

[isGlobalStore, ]target, soupName, options, callback);

パラメータisGlobalStore

(省略可能) true を渡して、データをグローバル SmartStore スープに同期します。target

スープにダウンロードする sObject を示します。次のいずれかの文字列にすることができます。• {type:"soql", query:"<soql query>"}

指定した SOQL クエリで返された sObject をダウンロードします。• {type:"sosl", query:"<sosl query>"}

指定した SOSL クエリで返された sObject をダウンロードします。• {type:"mru", sobjectType:"<sobject type>", fieldlist:"<fields to fetch>"}

指定した sObject 型の最近使用した sObject の指定した項目をダウンロードします。• {type:"custom", androidImpl:"<name of native Android target class (if supported)>",

iOSImpl:"<name of native iOS target class (if supported)>"}

特定のカスタムターゲットで指定されたレコードをダウンロードします。カスタムターゲットを使用する場合、androidImpl または iOSImpl、あるいはその両方 (推奨) を指定します。「カスタム下位同期ターゲットの使用」を参照してください。

soupName

ダウンロードされた sObject を受信するスープの名前。options

次のいずれかの値を使用します。• 変更されたローカルレコードを上書きする場合は、

{mergeMode:Force.MERGE_MODE_DOWNLOAD.OVERWRITE} を渡します。

273

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

• 変更されたローカルレコードを維持する場合は、{mergeMode:Force.MERGE_MODE_DOWNLOAD.LEAVE_IF_CHANGED} を渡します。この値を使用すると、ローカルで変更されたレコードが上書きされません。

callback

同期の開始後にコールされる関数。この関数は、同期操作中に複数回コールされます。1. 同期操作の開始時2. 内部 REST 要求の完了時3. 結果の各ページをダウンロード後 (結果を 100% 受信するまで)

同期操作の状況更新は、ブラウザイベントによって通知されます。これらの更新をリスンするには、次のコードを使用します。document.addEventListener("sync",

function(event) {// event.detail contains the status of the sync operation

});

event.detail メンバーには、次の項目との対応付けが含まれます。• syncId: この同期操作の ID

• type: 「syncDown」• target: 指定したターゲット• soupName: 指定したスープ名• options: 「{}」• status: 同期状況 (「新規」、「実行中」、「完了」、「失敗」のいずれか)

• progress: 現時点でダウンロード済みの合計レコードの割合 (整数、0 ~ 100%)

• totalSize: 現時点でダウンロード済みのレコード数

syncUp() メソッドsoupNameで指定したSmartStoreスープで作成、削除、または更新されたレコードをアップロードして、Salesforce

サーバの対応するレコードを更新、作成、または削除します。更新はブラウザイベントによって通知されます。構文cordova.require("com.salesforce.plugin.smartsync").syncUp(isGlobalStore, target, soupName,options, callback);

パラメータisGlobalStore

グローバル SmartStore を使用しているかどうかを示します。指定されていない場合、デフォルトの false

に設定されます。target

1 つ以上のカスタムターゲットネイティブクラスの名前 (カスタムターゲットを定義している場合)。「カスタム上位同期ターゲットの使用」を参照してください。

274

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

soupName

アップロードする sObject があるスープの名前options

次のキーとの対応付け:

• fieldlist: サーバに送信される項目のリスト• mergeMode:

– 変更されたリモートレコードを上書きする場合は、「OVERWRITE」を渡します。– 変更されたリモートレコードを維持する場合は、「LEAVE_IF_CHANGED」を渡します。この値を使用す

ると、サーバで変更されたレコードが上書きされません。– 指定されていない場合、デフォルトの「OVERWRITE」に設定されます。

callback

同期の開始後に複数回コールされる関数。同期操作中、この関数は次のようなイベントでコールされます。1. 同期操作の開始時2. 内部 REST 要求の完了時3. 結果の各ページをアップロード後 (結果を 100% 受信するまで)

同期操作の状況更新は、ブラウザイベントによって通知されます。これらの更新をリスンするには、次のコードを使用します。document.addEventListener("sync",

function(event) {// event.detail contains the status of the sync operation

});

event.detail メンバーには、次の項目との対応付けが含まれます。• syncId: この同期操作の ID

• type: 「syncUp」• target: 「{}」、または実装した Android および iOS カスタムターゲットクラスのクラス名を含む対応付

けやディクショナリ• soupName: 指定したスープ名• options:

– fieldlist: サーバに送信される項目のリスト– mergeMode: 「OVERWRITE」または「LEAVE_IF_CHANGED」

• status: 同期状況 (「新規」、「実行中」、「完了」、「失敗」のいずれか)

• progress: 現時点でダウンロード済みの合計レコードの割合 (整数、0 ~ 100%)

• totalSize: 現時点でダウンロード済みのレコード数

275

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

JavaScript での SmartSync Data Framework の使用ハイブリッドアプリケーションで SmartSync を使用するには、<script> タグを使用して次のファイルをインポートします。• jquery-x.x.x.min.js (SalesforceMobileSDK-Shared リポジトリの dependencies/jquery/ ディレクトリ

内のバージョンを使用)

• underscore-x.x.x.min.js (SalesforceMobileSDK-Shared リポジトリの dependencies/underscore/ ディレクトリ内のバージョンを使用)

• backbone-x.x.x.min.js (SalesforceMobileSDK-Sharedリポジトリの dependencies/backbone/ディレクトリ内のバージョンを使用)

• cordova.js

• forcetk.mobilesdk.js

• smartsync.js

モデルオブジェクトの実装SmartSync オブジェクトの使用を開始するには、操作する各 SObject を表すモデルオブジェクトを定義します。SObjectsは、標準 Salesforce オブジェクトまたはカスタムオブジェクトになります。たとえば、次のコードは、2 つの必須プロパティ (sobjectTypeおよび fieldlist) を設定する Account オブジェクトのモデルを作成し、cacheMode() 関数を定義します。app.models.Account = Force.SObject.extend({

sobjectType: "Account",fieldlist: ["Id", "Name", "Industry", "Phone"],

cacheMode: function(method) {if (app.offlineTracker.get("offlineStatus") == "offline") {

return "cache-only";}else {

return (method == "read" ?"cache-first" : "server-first");

}}

});

app.models.Account モデルオブジェクトは、smartsync.js で定義されている Force.SObject を拡張します。また、cacheMode() 関数は、ローカル offlineTracker オブジェクトをクエリして、デバイスのオフライン状況を取得します。Cordova ライブラリを使用して、特定時点のオフライン状況を判断できます。SmartSyncは、モデルに対して取得操作または保存操作を実行できます。アプリケーションの cacheModeの値を使用して、操作の実行対象 (サーバまたはキャッシュ) を決定します。cacheMode メンバーは、単純な string

型のプロパティか、文字列を返す関数のいずれかになります。

276

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

モデルコレクションの実装このサンプルアプリケーションのモデルコレクションは、Force.SObjectCollection を拡張します。// The AccountCollection Modelapp.models.AccountCollection = Force.SObjectCollection.extend({

model: app.models.Account,fieldlist: ["Id", "Name", "Industry", "Phone"],setCriteria: function(key) {

this.key = key;},config: function() {

// Offline: do a cache queryif (app.offlineTracker.get("offlineStatus") == "offline") {

return {type:"cache", cacheQuery:{queryType:"like",indexPath:"Name", likeKey: this.key+"%",order:"ascending"}};

}// Onlineelse {

// First time: do a MRU queryif (this.key == null) {

return {type:"mru", sobjectType:"Account",fieldlist: this.fieldlist};

}// Other times: do a SOQL queryelse {

var soql = "SELECT " + this.fieldlist.join(",")+ " FROM Account"+ " WHERE Name like '" + this.key + "%'";

return {type:"soql", query:soql};}

}}

});

このモデルコレクションは、コレクションから取得する取引先の名前であるキー (省略可能) を使用します。また、取得される情報を決定する config()関数も定義します。デバイスがオフラインの場合、config()関数はキャッシュクエリステートメントを作成します。デバイスがオンラインで、キーが指定されていない場合、最後に使用したレコード ("mru") をクエリします。デバイスがオンラインで、キーが指定されている場合、キーに一致する名前のレコードを取得する標準 SOQL クエリを作成します。Force.SObjectCollectionプロトタイプの取得操作は、返された設定を透過的に使用して、モデルコレクションにクエリレコードを自動的に入力します。キャッシュクエリの書式設定についての詳細は、「querySpec」を参照してください。

メモ: これらのコード例は、Account Editor サンプルアプリケーションの一部です。サンプルの説明は、「Account Editor のサンプル」を参照してください。

オフラインキャッシュオフラインサポートを提供するには、アプリケーションでそのモデルおよびコレクションをキャッシュできる必要があります。SmartSync は、キャッシュの操作を完全に制御できるメカニズム (設定可能) を提供します。

277

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

デフォルトキャッシュおよびカスタムキャッシュの実装デフォルトキャッシュの場合、SmartSync ライブラリは StoreCache (SmartStore を使用するキャッシュ実装) を定義します。StoreCache と SmartStoreはどちらも SmartSyncアプリケーションのコンポーネント (省略可能) です。アプリケーションがMobile SDKコンテナではなくブラウザで実行されている場合や、SmartStoreを使用しない場合、代替キャッシュ実装を提供する必要があります。SmartSyncでは、次の操作をサポートするためにキャッシュオブジェクトが必要になります。• retrieve

• save

• save all

• remove

• find

SmartSync のキャッシュワークフローSmartSync モデルは、アプリケーションの代わりにキャッシュおよび Salesforce サーバとのすべてのやり取りを実行します。アプリケーションは、モデルオブジェクトの属性を取得および設定します。モデルは、保存操作時にこれらの属性設定を使用して、変更をキャッシュまたはサーバに書き込むかどうかを判断したり、新しいデータと既存のデータのマージ方法を決定したりします。基本データまたはモデル自体に何らかの変更があると、モデルはイベント通知を送信します。同様に、取得を要求すると、モデルはモデルコレクションでデータを取得してアプリケーションに提供します。

278

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

SmartSync は、CRUD 操作時にキャッシュのデータを透過的に更新します。フラグ (省略可能) を介して透過レベルを制御できます。キャッシュされたオブジェクトは、ローカルで作成、更新、削除されたかどうかを示す「dirty」属性を保持します。

キャッシュモデルキャッシュを使用する場合、各 CRUD 操作のモデルを指定できます。サポートされるモードは次のとおりです。

説明定数モード

キャッシュから読み取るか、キャッシュに書き込

Force.CACHE_MODE.CACHE_ONLY"cache-only"

みます。サーバの操作は実行しません。

サーバから読み取るか、サーバに書き込みます。

Force.CACHE_MODE.SERVER_ONLY"server-only"

キャッシュの操作は実行しません。

取得操作の場合のみ。キャッシュからレコード

Force.CACHE_MODE.CACHE_FIRST"cache-first"

を取得します。キャッシュにレコードが含まれていない場合、サーバから取得してキャッシュを更新します。

サーバの操作を実行し、キャッシュを更新します。

Force.CACHE_MODE.SERVER_FIRST"server-first" (デフォルト)

直接キャッシュをクエリするには、キャッシュクエリを使用します。SmartStore は、クエリ API、独自のクエリ言語、Smart SQL を提供します。「スープからのデータの取得」を参照してください。

オフラインキャッシュの実装SmartSyncでオフラインキャッシュをサポートするには、次のようないくつかのタスクを実装する必要があります。• app.models.Account の例で示すようにオフライン状況を追跡して、CRUD 操作の適切なキャッシュコン

トロールフラグを指定する。• ローカルで編集されたレコードを収集し、デバイスがオンラインに戻ったときにその変更をサーバに保存

する。次の例では、SmartStore キャッシュクエリを使用して、ローカルで変更されたレコードを取得し、SyncPage 関数をコールして、HTML でその結果を表示しています。sync: function() {var that = this;

279

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

var localAccounts = new app.models.AccountCollection();localAccounts.fetch({config: {type:"cache", cacheQuery: {queryType:"exact",

indexPath:"__local__", matchKey:true}},success: function(data) {that.slidePage(new app.views.SyncPage({model: data}).render());}});}

app.views.SyncPage = Backbone.View.extend({

template: _.template($("#sync-page").html()),

render: function(eventName) {$(this.el).html(this.template(_.extend(

{countLocallyModified: this.model.length},this.model.toJSON())));

this.listView = new app.views.AccountListView({el: $("ul", this.el), model: this.model});

this.listView.render();return this;

},...});

オフラインキャッシュのための StoreCache の使用smartsync.js ライブラリは、データを SmartStore に保存する StoreCache という名前のキャッシュを実装します。SmartSyncは StoreCache をデフォルトキャッシュとして使用しますが、StoreCache はスタンドアロンコンポーネントです。SmartSync を使用しない場合でも、SmartStore の操作に StoreCache を活用できます。

メモ: StoreCache は SmartSync と併用することを想定していますが、「オフラインキャッシュ」で説明されているように、要件を満たす任意のキャッシュメカニズムを SmartSync と共に使用することもできます。

作成および初期化StoreCache オブジェクトは、内部的にSmartStoreスープと連動します。スープ soupNameによってサポートされる StoreCache オブジェクトを作成するには、次のコンストラクタを使用します。new Force.StoreCache(soupName [, additionalIndexSpecs, keyField])

soupName

必須。基盤となる SmartStore スープの名前。additionalIndexSpecs

デフォルトのインデックス項目に加えてキャッシュインデックスに含める項目。書式設定の手順は、「スープの登録」を参照してください。

keyField

レコード ID を格納する項目の名前。指定しない場合、StoreCache は "Id" という名前の項目で ID を検索します。

280

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

StoreCache オブジェクトのスープ項目には、オフライン編集を追跡する次の 4 つの追加の Boolean 項目が含まれます。• __locally_created__

• __locally_updated__

• __locally_deleted__

• __local__ (前の 3 つのいずれかが true の場合、true に設定)

これらの項目は内部で使用することを目的としていますが、アプリケーションでも使用できます。StoreCache

は、 __local__項目およびその ID 項目の各スープにインデックスを付けます。additionalIndexSpecsパラメータを使用して、インデックスに含める追加項目を指定できます。基盤となるスープを登録するには、StoreCache オブジェクトで init() をコールします。この関数は、スープの登録が完了したときに解決する jQuery promise を返します。

StoreCache メソッドinit()

基盤となる SmartStoreスープを登録します。スープの登録が完了したときに解決さる jQuery promise を返します。

retrieve(key [, fieldlist])

SmartStoreによって返される keyField のキーを持つレコードに解決する jQuery promise を返します。レコードが検出されない場合や、検出されたレコードに fieldlist パラメータのすべての項目が含まれていない場合、promise は null に解決されます。key

取得されるレコードのキー値。fieldlist

(省略可能) 必須項目の JavaScript 配列。次に例を示します。["field1","field2","field3"]

save(record [, noMerge])

SmartStoreの更新/挿入が完了したときに、保存されたレコードに解決する jQuery promise を返します。noMerge

が指定されていない場合や、false の場合、渡されたレコードは、同じキーのサーバレコード (存在する場合)

とマージされます。record

保存されるレコード。次のような形式になります。{<field_name1>:"<field_value1>"[,<field_name2>:"<field_value2>",...]}

次に例を示します。{Id:"007", Name:"JamesBond", Mission:"TopSecret"}

noMerge

(省略可能) 渡されたレコードが、一致するサーバレコードとマージされるかどうかを示す boolean 値。デフォルトは false です。

281

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

saveAll(records [, noMerge])

records が、保存されるレコードの配列である点を除き、save() と同じです。保存されるレコードに解決する jQuery promise を返します。records

レコードの配列。配列の各項目は、save() 関数に示されるように書式設定されます。noMerge

(省略可能) 渡されたレコードが、一致するサーバレコードとマージされるかどうかを示す boolean 値。デフォルトは false です。

remove(key)

指定されたキーを持つレコードが SmartStore から削除されたときに解決する jQuery promise を返します。key

削除されるレコードのキー値。find(querySpec)

SmartStore に対してクエリが実行されたときに解決する jQuery promise を返します。解決される値は、次の項目を持つオブジェクトです。

説明項目

取得されたすべてのレコードrecords

さらにレコードを取得できるかどうかをチェックする関数

hasMore

さらにレコードを取得する関数getMore

開いているカーソルを閉じて、今後の取得を無効にする関数

closeCursor

querySpec

SmartStore クエリ関数コールに基づく仕様。次のような形式になります。{queryType: "like" | "exact" | "range" | "smart"[, query_type_params]}

ここで、query_type_params は、関連する SmartStore クエリ関数コールの形式に一致します。「スープからのデータの取得」を参照してください。次に、いくつか例を示します。{queryType:"exact", indexPath:"<indexed_field_to_match_on>", matchKey:<value_to_match>,order:"ascending"|"descending", pageSize:<entries_per_page>}

{queryType:"range", indexPath:"<indexed_field_to_match_on>", beginKey:<start_of_Range>,endKey:<end_of_range>, order:"ascending"|"descending", pageSize:<entries_per_page>}

{queryType:"like", indexPath:"<indexed_field_to_match_on>", likeKey:"<value_to_match>",order:"ascending"|"descending", pageSize:<entries_per_page>}

282

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

{queryType:"smart", smartSql:"<smart_sql_query>", order:"ascending"|"descending",pageSize:<entries_per_page>}

例次の例では、StoreCache オブジェクトの作成、初期化、使用方法を示します。var cache = new Force.StoreCache("agents", [{path:"Mission", type:"string"} ]);// initialization of the cache / underlying soupcache.init().then(function() {

// saving a record to the cachereturn cache.save({Id:"007", Name:"JamesBond", Mission:"TopSecret"});

}).then(function(savedRecord) {

// retrieving a record from the cachereturn cache.retrieve("007");

}).then(function(retrievedRecord) {

// searching for records in the cachereturn cache.find({queryType:"like", indexPath:"Mission", likeKey:"Top%",

order:"ascending", pageSize:1});}).then(function(result) {

// removing a record from the cachereturn cache.remove("007");

});

次の例では、saveAll() 関数の使用方法と find() 関数の結果を示します。// initializationvar cache = new Force.StoreCache("agents", [ {path:"Name", type:"string"}, {path:"Mission",type:"string"} ]);cache.init().then(function() {

// saving some recordsreturn cache.saveAll([{Id:"007", Name:"JamesBond"},{Id:"008", Name:"Agent008"},

{Id:"009", Name:"JamesOther"}]);}).then(function() {

// doing an exact queryreturn cache.find({queryType:"exact", indexPath:"Name", matchKey:"Agent008",

order:"ascending", pageSize:1});}).then(function(result) {

alert("Agent mission is:" + result.records[0]["Mission"];});

283

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

競合検出モデルオブジェクトは、オブジェクトをサーバに保存するときに不要なデータ損失を回避する競合検出 (省略可能) をサポートしています。競合検出は、デバイスがオフライン状態から復帰しているかどうかに関係なく、任意の保存操作と共に使用できます。競合検出をサポートするには、サーバから取得した元の値を格納するセカンダリキャッシュを指定します。SmartSyncは、後で参照できるようにこのキャッシュを保持します。保存または削除する場合、マージモードを指定します。次の表に、サポートされるモードの概要を示します。モードの説明を理解するには、「theirs」を現在のサーバレコード、「yours」を現在のローカルレコード、「base」をサーバから最初に取得したレコードとして考えます。

説明モードの定数

「theirs」または「base」と比較することなく「yours」を

Force.MERGE_MODE.OVERWRITE

サーバに書き込みます。これは、競合検出を使用しない場合と同じです。

「theirs」と「yours」をマージします。同じ項目がローカル

Force.MERGE_MODE.MERGE_ACCEPT_YOURS

とリモートの両方で変更された場合、ローカルの値が保持されます。

「theirs」と「yours」をマージします。同じ項目がローカル

Force.MERGE_MODE.MERGE_FAIL_IF_CONFLICT

とリモートの両方で変更された場合、この操作は失敗します。

「theirs」と「yours」をマージします。何らかの項目がリ

Force.MERGE_MODE.MERGE_FAIL_IF_CHANGED

モートで変更された場合、この操作は失敗します。

保存または削除操作が失敗した場合、次の項目を含むレポートオブジェクトを取得します。

次の文字列を含む項目名

最初に取得した属性base

最新のサーバ属性theirs

284

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

次の文字列を含む項目名

ローカルで変更された属性yours

base と theirs 間で変更された項目のリストremoteChanges

base と yours 間で変更された項目のリストlocalChanges

異なる値を使用して theirs と yours の両方で変更された項目のリスト

conflictingChanges

ダイアグラムは、マージモードの仕組みを明確にするのに役立ちます。

MERGE_MODE.OVERWRITE

MERGE_MODE.OVERWRITE ダイアグラムでは、クライアントは A と B を変更し、サーバは B と C を変更しています。B への変更は競合していますが、A と C への変更は競合していません。ただし、保存操作では、すべてのクライアントの値が無差別にサーバに書き込まれるため、サーバの変更が上書きされます。

MERGE_ACCEPT_YOURS

MERGE_MODE.MERGE_ACCEPT_YOURS ダイアグラムでは、クライアントは A と B を変更し、サーバは B と C を変更しています。競合があるかどうかに関係なく、クライアントの変更 (A と B) によってサーバの対応する項目が上書きされます。ただし、クライアントが変更しなかった項目 (C) では、対応するサーバの値は上書きされません。

MERGE_FAIL_IF_CONFLICT (失敗)

最初の MERGE_MODE.MERGE_FAIL_IF_CONFLICT ダイアグラムでは、クライアントとサーバの両方が B を変更しています。これらの競合する変更が原因で保存操作が失敗します。

285

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

MERGE_FAIL_IF_CONFLICT (成功)

2 番目の MERGE_MODE.MERGE_FAIL_IF_CONFLICTダイアグラムでは、クライアントは A を変更し、サーバはB を変更しています。これらの変更は競合しないため、保存操作は成功します。

ミニチュートリアル: 競合検出次のミニチュートリアルでは、さまざまな状況下でマージモードが保存操作にどのような影響を与えるかについて説明します。HTML コンテキスト内のさまざまな例を挙げて説明します。1. 必要なキャッシュを設定します。

var cache = new Force.StoreCache(soupName);var cacheForOriginals =

new Force.StoreCache(soupNameForOriginals);var Account = Force.SObject.extend({

sobjectType:"Account",fieldlist:["Id", "Name", "Industry"],cache:cache,cacheForOriginals:cacheForOriginals});

2. 既存の取引先を取得します。var account = new Account({Id:<some actual account id>});account.fetch();

3. 取引先の名前が「Acme」で業種が「ソフトウェア」だとします。名前を「Acme2」に変更します。Account.set("Name", "Acme2");

286

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

4. デフォルトの "overwrite" マージモードが使用されるように、マージモードを指定せずにサーバに保存します。account.save(null);

取引先の名前が「Acme2」でその業種が「ソフトウェア」になりました。サーバ上の業種が「電子機器」に変更されるとします。

5. 取引先名を再度変更します。Account.set("Name", "Acme3");

現在、キャッシュの変更 (名前) とサーバの変更 (業種) があります。6. "merge-fail-if-changed" マージモードを使用して再度保存します。

account.save(null,{mergeMode: "merge-fail-if-changed", error: function(err) {// err will be a map of the form:// {base:…, theirs:…, yours:…,// remoteChanges:["Industry"], localChanges:["Name"],// conflictingChanges:[]}

});

サーバレコードが変更されているため、エラーコールバックがコールされます。7. "merge-fail-if-conflict" マージモードを使用して再度保存します。サーバの変更とクライアントの変更間で競合

が存在しないため、このマージは成功します。account.save(null, {mergeMode: "merge-fail-if-conflict"});

取引先の名前は「Acme3」(yours) で、その業種は「電子機器」(theirs) になりました。一方、サーバ上の名前が「NewAcme」、業種が「サービス」に変更されるとします。

8. 取引先名を再度変更します。Account.set("Name", "Acme4");

9. "merge-fail-if-changed" マージモードを使用して再度保存します。サーバレコードが変更されているため、エラーコールバックがコールされます。account.save(null, {mergeMode: "merge-fail-if-changed", error: function(err) {

// err will be a map of the form:// {base:…, theirs:…, yours:…,// remoteChanges:["Name", "Industry"],// localChanges:["Name"], conflictingChanges:["Name"]}

});

10. "merge-fail-if-conflict" マージモードを使用して再度保存します。account.save(null, {mergeMode: "merge-fail-if-changed", error: function(err) {

// err will be a map of the form:// {base:…, theirs:…, yours:…,// remoteChanges:["Name", "Industry"],// localChanges:["Name"], conflictingChanges:["Name"]}

});

287

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

サーバとキャッシュの両方で名前項目が変更されて競合が発生しているため、エラーコールバックがコールされます。

11. "merge-accept-yours" マージモードを使用して再度保存します。マージモードでは、どちらの名前の値を受け入れるかが save() 関数に通知されているため、このマージは成功します。また、業種を変更していないため、この項目は競合しません。account.save(null, {mergeMode: "merge-accept-yours"});

名前は「Acme4」(yours) で、業種は「サービス」(theirs) です。どちらもキャッシュとサーバにあります。

カスタム API エンドポイントへのアクセスMobile SDK 2.1 では、SmartSync の範囲が拡張されており、REST API と併用できるようになっています。以前は、Force.com API を使用して sObject に基本的な操作しか実行できませんでした。Apex REST オブジェクト、Chatter

Files、および他の Salesforce REST API と SmartSync を併用できるようになりました。 また、非 Salesforce REST API をコールすることもできます。

Force.RemoteObject クラス任意の REST コールをサポートするために、SmartSync には Force.RemoteObject 抽象クラスが導入されています。Force.RemoteObject は、Force.SObject と Backbone.Model 間の抽象化レイヤとして機能します。Force.SObject は、Backbone.Model を直接サブクラス化するのではなく、Backbone.Model をサブクラス化する Force.RemoteObjectをサブクラス化するようになりました。Force.RemoteObjectは、サーバとの通信を除き、Force.SObject が以前に行っていたすべてのことを実行します。

syncRemoteObjectWithServer() を使用したカスタムエンドポイントのコール

RemoteObject.syncRemoteObjectWithServer()プロトタイプメソッドは、サーバとのやりとりを処理します。Force.SObject は、syncRemoteObjectWithServer() を実装して Force.com REST API を使用します。他のサーバエンドポイントを使用する場合、Force.RemoteObject のサブクラスを作成し、syncRemoteObjectWithServer() を実装します。このメソッドは、サブクラスのオブジェクトに対してfetch()をコールしたときにコールされます (サーバから取得するようにオブジェクトが現在設定されている場合)。

例: 例

HybridFileExplorer サンプルアプリケーションは、Force.RemoteObjectの使用方法を示す SmartSyncアプリケーションです。HybridFileExplorer は、Chatter REST API をコールしてファイルを操作します。これは、Force.RemoteObject を拡張する app.models.File オブジェクトを定義します。app.models.File

は、syncRemoteObjectWithServer() の実装で /chatter/files/fileId REST API をラップするforcetk.fileDetails() をコールします。app.models.File = Force.RemoteObject.extend({

syncRemoteObjectWithServer: function(method, id) {if (method != "read")

throw "Method not supported " + method;return Force.forcetkClient.fileDetails(id, null);

}})

288

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

Force.RemoteObjectCollection クラス取得されたオブジェクトのコレクションをサポートするために、SmartSync にはForce.RemoteObjectCollection 抽象クラスが導入されています。このクラスは、Force.SObjectCollection と Backbone.Collection 間の抽象化レイヤとして機能します。Force.SObjectCollection

は、Backbone.Collection を直接サブクラス化するのではなく、Backbone.Collection をサブクラス化するForce.RemoteObjectCollection をサブクラス化するようになりました。Force.RemoteObjectCollectionは、サーバとの通信を除き、Force.SObjectCollection が以前に行っていたすべてのことを実行します。

fetchRemoteObjectFromServer() を使用してカスタムエンドポイントを実装するRemoteObject.fetchRemoteObjectFromServer() プロトタイプメソッドは、サーバとのやりとりを処理します。このメソッドは Force.com REST API を使用して SOQL/SOSL および MRU クエリを実行します。任意のサーバエンドポイントを使用する場合、Force.RemoteObjectCollection のサブクラスを作成し、fetchRemoteObjectFromServer() を実装します。このメソッドは、サブクラスのオブジェクトに対してfetch()をコールしたときにコールされます (サーバから取得するようにオブジェクトが現在設定されている場合)。app.models.FileCollection.fetchRemoteObjectsFromServer() 関数が返されると、応答のメタデータを使用する有効な情報や、便利な関数を格納するオブジェクトが promise 化されます。このオブジェクトには、次が含まれます。• totalSize: 返されたコレクションのファイル数• records: 返されたファイルのコレクション• hasMore: 結果の別のページを取得できるかどうかを示す boolean 値を返す関数• getMore: 結果の次のページを取得する関数 (hasMore() で true が返された場合)

• closeCursor: コレクションの反復処理が終了したことを示す関数これらの関数は、サーバ応答に含まれている情報 (Files.length や nextPageUrl など) を利用します。

例: 例

HybridFileExplorer サンプルアプリケーションでは、Force.RemoteObjectCollection の使用方法も示します。この例では、Chatter REST APIをコールして、ファイルのリストを反復処理します。ownedFilesList、filesInUsersGroups、および filesSharedWithUser の 3 つの REST 操作がサポートされています。この例の hasMore() や getMore() などの関数を記述して、結果のページを移動できます。ただし、アプリケーションは直接 fetchRemoteObjectsFromServer() をコールしないため、コレクションオブジェクトで fetch() をコールすると返される promise オブジェクトをキャプチャします。app.models.FileCollection = Force.RemoteObjectCollection.extend({

model: app.models.File,

setCriteria: function(key) {this.config = {type:key};

},

fetchRemoteObjectsFromServer: function(config) {var fetchPromise;switch(config.type) {

case "ownedFilesList": fetchPromise =

289

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

Force.forcetkClient.ownedFilesList("me", 0);break;

case "filesInUsersGroups": fetchPromise =Force.forcetkClient.

filesInUsersGroups("me", 0);break;

case "filesSharedWithUser": fetchPromise =Force.forcetkClient.

filesSharedWithUser("me", 0);break;

};

return fetchPromise.then(function(resp) {

var nextPageUrl = resp.nextPageUrl;return {

totalSize: resp.files.length,records: resp.files,hasMore: function() {

return nextPageUrl != null; },getMore: function() {

var that = this;if (!nextPageUrl)

return null;return

forcetkClient.queryMore(nextPageUrl).then(function(resp) {

nextPageUrl = resp.nextPageUrl;that.records.

pushObjects(resp.files);return resp.files;

});},closeCursor: function() {

return $.when(function() {nextPageUrl = null;

});}

};});

}});

Apex REST リソースの使用Apex REST リソースをサポートするために、Mobile SDK には、Force.ApexRestObject とForce.ApexRestObjectCollection の 2 つのクラスが用意されています。これらのクラスは、それぞれForce.RemoteObject と Force.RemoteObjectCollection をサブクラス化し、Apex REST を使用して作成した REST API と通信できます。

290

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

Force.ApexRestObject

Force.ApexRestObject は、Force.SObject と似ています。sobjectType の代わりに、Force.ApexRestObjectには services/apexrestを基準とする Apex REST リソースの相対パスが必要です。たとえば、リソースのフルパスが services/apexrest/simpleAccount/*の場合、/simpleAccount/*のみを指定します。また、Force.ApexRestObject では、ID 項目名が「Id」以外の場合、その名前を指定する必要があります。

例: 例

accountId と accountName の 2 つの項目を含む取引先である「simple account」(簡単な取引先) という名前の Apex REST リソースを作成したとします。@RestResource(urlMapping='/simpleAccount/*')global with sharing class SimpleAccountResource {

static String getIdFromURI() {RestRequest req = RestContext.request;return req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);

}

@HttpGet global static Map&lt;String, String&gt; doGet() {String id = getIdFromURI();Account acc = [select Id, Name from Account

where Id = :id];return new Map&lt;String, String&gt;{

'accountId'=>acc.Id, 'accountName'=>acc.Name};}

@HttpPost global static Map&lt;String, String&gt;doPost(String accountName) {

Account acc = new Account(Name=accountName);insert acc;return new Map&lt;String, String&gt;{

'accountId'=>acc.Id, 'accountName'=>acc.Name};}

@HttpPatch global static Map&lt;String, String&gt;doPatch(String accountName) {

String id = getIdFromURI();Account acc = [select Id from Account

where Id = :id];acc.Name = accountName;update acc;return new Map&lt;String, String&gt;{

'accountId'=>acc.Id, 'accountName'=>acc.Name};}

@HttpDelete global static void doDelete() {String id = getIdFromURI();Account acc = [select Id from Account where Id = :id];delete acc;RestContext.response.statusCode = 204;

}}

291

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

SmartSync で、次を実行して「simple account」を作成します。var SimpleAccount = Force.ApexRestObject.extend(

{apexRestPath:"/simpleAccount",idAttribute:"accountId",fieldlist:["accountId", "accountName"]});

var acc = new SimpleAccount({accountName:"MyFirstAccount"});acc.save();

その「simple account」を更新できます。acc.set("accountName", "MyFirstAccountUpdated");acc.save(null, {fieldlist:["accountName"]);// our apex patch endpoint only expects accountName

別の「simple account」を取得できます。var acc2 = new SimpleAccount({accountId:"&lt;valid id&gt;"})acc.fetch();

「simple account」を削除できます。acc.destroy();

メモ: 通常、SmartSyncのコール (fetch()、save()、および destroy()など) では、成功コールバック関数およびエラーコールバック関数を定義するオプションパラメータを渡します。次に例を示します。acc.destroy({success:function(){alert("delete succeeded");}});

Force.ApexRestObjectCollection

Force.ApexRestObjectCollectionは、Force.SObjectCollectionと似ています。取得用に指定する設定では、SOQL、SOSL、または MRU がサポートされていません。代わりに、services/apexrestを基準とするApex REST リソースの相対パスが必要です。たとえば、リソースのフルパスがservices/apexrest/simpleAccount/* の場合、/simpleAccount/* のみを指定します。エンドポイントでクエリ文字列のパラメータがサポートされていれば、これらを渡すこともできます。Apex

REST エンドポイントは、次の形式で応答を返す必要があります。{ totalSize: <number of records returned>

records: <all fetched records>nextRecordsUrl: <url to get next records or null>

}

例: 例

「simple account」という名前の Apex REST リソースを作成したとします。これは、指定された名前と一致する「simple account」を返します。@RestResource(urlMapping='/simpleAccounts/*')global with sharing class SimpleAccountsResource {

@HttpGet global static SimpleAccountsList doGet() {String namePattern =

292

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

RestContext.request.params.get('namePattern');List<SimpleAccount> records = new List<SimpleAccount>();for (SObject sobj : Database.query(

'select Id, Name from Accountwhere Name like \'' + namePattern + '\'')) {

Account acc = (Account) sobj;records.add(new

SimpleAccount(acc.Id, acc.Name));}return new SimpleAccountsList(records.size(), records);

}

global class SimpleAccountsList {global Integer totalSize;global List<SimpleAccount> records;

global SimpleAccountsList(Integer totalSize,List<SimpleAccount> records) {

this.totalSize = totalSize;this.records = records;

}}

global class SimpleAccount {global String accountId;global String accountName;

global SimpleAccount(String accountId, String accountName){

this.accountId = accountId;this.accountName = accountName;

}}

}

SmartSync で、次を実行して「simple account」レコードのリストを取得します。var SimpleAccountCollection =

Force.ApexRestObjectCollection.extend({model: SimpleAccount,config:{

apexRestPath:"/simpleAccounts",params:{namePattern:"My%"}

}}

);var accs = new SimpleAccountCollection();accs.fetch();

メモ: 通常、SmartSyncのコール (fetch()など) では、成功コールバック関数およびエラーコールバック関数を定義するオプションパラメータを渡します。次に例を示します。acc.fetch({success:function(){alert("fetched " +

accs.models.length + " simple accounts");}});

293

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

チュートリアル: ハイブリッド SmartSync アプリケーションの作成このチュートリアルでは、SmartSync Data Framework を使用するローカルハイブリッドアプリケーションの作成方法について説明します。Mobile SDK に付属する UserSearch のサンプルアプリケーションを再作成します。UserSearch では、Salesforce 組織のユーザレコードを検索し、ユーザレコードに関する基本情報の詳細を確認できます。このサンプルでは、次の Web テクノロジを使用しています。• Backbone.js

• Ratchet

• HTML5

• JavaScript

テンプレートプロジェクトの作成まず、NPM インストーラを使用して Salesforce Mobile SDKをインストールしていることを確認します。iOS の手順は、「iOS のインストール」を参照してください。Android の手順は、「Android のインストール」を参照してください。また、http://goratchet.com/ から ratchet.css ファイルをダウンロードします。Mobile SDK をインストールしたら、プラットフォームのローカルハイブリッドプロジェクトを作成します。1. ターゲットプラットフォームが iOS の場合:

a. Mac OS X ターミナルウィンドウで次のコマンドを入力します。forceios create --apptype=hybrid_local

--appname=UserSearch --companyid=com.acme.usersearch--organization=Acme --outputdir=.

b. 接続アプリケーション ID および接続アプリケーションコールバック URI のプロンプトで Return キーを押します。forceios スクリプトによって、./UserSearch/UserSearch.xcode.proj にプロジェクトが作成されます。

2. ターゲットプラットフォームが Android の場合:

a. Mac OS X ターミナルウィンドウまたは Windows コマンドプロンプトで次のコマンドを入力します。forcedroid create --apptype="hybrid_local"

--appname="UserSearch" --targetdir=.--packagename="com.acme.usersearch"

b. 接続アプリケーション ID および接続アプリケーションコールバック URI のプロンプトで Return キーを押します。forcedroid スクリプトによって ./UserSearch にプロジェクトが作成されます。

3. cd で新しいプロジェクトのルートディレクトリに切り替えます。

294

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

4. 次のように、すべてのファイル (実際のファイルとシンボリックファイル) をhttps://github.com/forcedotcom/SalesforceMobileSDK-Shared/ リポジトリの samples/usersearch ディレクトリから www/ フォルダにコピーします。• Mac OS X ターミナルウィンドウで、プロジェクトのルートディレクトリに変更し、次のコマンドを入力

します。cp -RL <insert local path to SalesforceMobileSDK-Shared>/samples/UserSearch/* www/

• Windows で、<shared repo>\samples\usersearch フォルダで参照されるすべてのファイルが<project_name>\wwwフォルダにも表示されていることを確認します。次のスクリプトに示すように、シンボリックリンクを明示的に解決します。cd <your project’s root directory>set SHARED_REPO=<insert local path to SalesforceMobileSDK-Shared>copy %SHARED_REPO%\samples\usersearch\UserSearch.html wwwcopy %SHARED_REPO%\samples\usersearch\bootconfig.json wwwcopy %SHARED_REPO%\dependencies\ratchet\ratchet.css wwwcopy %SHARED_REPO%\samples\common\styles.css wwwcopy %SHARED_REPO%\test\MockCordova.js wwwcopy %SHARED_REPO%\samples\common\auth.js wwwcopy %SHARED_REPO%\dependencies\backbone\backbone-min.js wwwcopy %SHARED_REPO%\libs\cordova.force.js wwwcopy %SHARED_REPO%\dependencies\fastclick\fastclick.js wwwcopy %SHARED_REPO%\libs\forcetk.mobilesdk.js wwwcopy %SHARED_REPO%\libs\forcetk.ui.js wwwcopy %SHARED_REPO%\dependencies\jquery\jquery.min.js wwwcopy %SHARED_REPO%\libs\smartsync.js wwwcopy %SHARED_REPO%\samples\common\stackrouter.js wwwcopy %SHARED_REPO%\dependencies\underscore\underscore-min.js www

5. 次のコマンドを実行します。cordova prepare

6. forcedroid または forceios で出力される画面の指示に従って、Android Studio (Android の場合) または Xcode (iOS の場合) で新しいプロジェクトを開きます。

7. wwwフォルダから、コードエディタを使用して UserSearch.htmlを開き、そのすべてのコンテンツを削除します。

アプリケーションの HTML ファイルの編集アプリケーションの基本構造を作成するには、参照、リンク、コードインフラストラクチャを格納する空のHTML ページを定義します。1. Xcode で、UserSearch.html を編集して次の基本構造を追加します。

<!DOCTYPE html><html><head></head><body>

295

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

</body></html>

2. <head> 要素で、次の操作を行います。a. ページタイトルが「Users」であることを指定します。

<title>Users</title>

b. Web ページではなくアプリケーションのようなページにするために拡大縮小を無効にします。<meta name="viewport" content="width=device-width, initial-scale=1.0,

maximum-scale=1.0, user-scalable=no;" />

c. モバイル用の「外観」になるように styles.css および ratchet.css ファイルへのリンクを追加します。<link rel="stylesheet" href="css/styles.css"/><link rel="stylesheet" href="css/ratchet.css"/>

3. コンテンツを本文に追加します。<body> ブロックで、ID が「content」に設定された空の div タグを追加して、アプリケーションの生成された UI を格納します。<body><div id="content"></div>

4. 必要な JavaScript ファイルを含めます。<script src="js/jquery.min.js"></script><script src="js/underscore-min.js"></script><script src="js/backbone-min.js"></script><script src="js/forcetk.mobilesdk.js"></script><script src="cordova.js"></script><script src="js/smartsync.js"></script><script src="js/fastclick.js"></script><script src="js/stackrouter.js"></script><script src="js/auth.js"></script>

例: 次に、この時点の完全なアプリケーションを示します。<!DOCTYPE html><html><head><title>Users</title><meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1.0;user-scalable=no" />

<link rel="stylesheet" href="css/styles.css"/><link rel="stylesheet" href="css/ratchet.css"/>

</head><body><div id="content"></div><script src="js/jquery.min.js"></script><script src="js/underscore-min.js"></script>

296

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

<script src="js/backbone-min.js"></script><script src="js/forcetk.mobilesdk.js"></script><script src="cordova.js"></script><script src="js/smartsync.js"></script><script src="js/fastclick.js"></script><script src="js/stackrouter.js"></script><script src="js/auth.js"></script>

</body></html>

SmartSync モデルおよびコレクションの作成HTML インフラストラクチャを設定したので、次の 2 つの主オブジェクトを拡張して SmartSync を使用します。• Force.SObject

• Force.SObjectCollection

これらのオブジェクトは、Backbone.Model.extend()関数をサポートできるように Backbone.Modelを拡張します。この関数を使用してオブジェクトを拡張するには、カスタムプロパティおよびカスタム機能を含むJavaScript オブジェクトに渡します。1. <body> タグで、<script> オブジェクトを作成します。2. <body> タグで、Salesforce user sObject のモデルオブジェクトを作成します。Force.SObject を拡張して、

対象とする sObject タイプおよび項目を指定します。app.models.User = Force.SObject.extend({

sobjectType: "User",fieldlist: ["Id", "FirstName", "LastName",

"SmallPhotoUrl", "Title", "Email","MobilePhone","City"]

})

3. User オブジェクトの設定直後に、User Search 結果を保持するコレクションを作成します。Force.SObjectCollection を拡張して、コレクションの項目のモデルとして新しいモデル(app.models.User) を指定します。app.models.UserCollection = Force.SObjectCollection.extend({

model: app.models.User,fieldlist: ["Id", "FirstName", "LastName",

"SmallPhotoUrl", "Title"],

});

4. このコレクションでは、検索キーを取得し、それを使用して SOQL クエリを作成する setCriteria という名前の関数を実装します。また、後でキーを返す getter も必要です。<script>

// The Models// ==========// The User Modelapp.models.User = Force.SObject.extend({

sobjectType: "User",

297

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

fieldlist: ["Id", "FirstName","LastName", "SmallPhotoUrl","Title", "Email","MobilePhone","City"]

});

// The UserCollection Modelapp.models.UserCollection = Force.SObjectCollection.extend({

model: app.models.Userfieldlist: ["Id", "FirstName", "LastName",

"SmallPhotoUrl", "Title"],

getCriteria: function() {return this.key;

},

setCriteria: function(key) {this.key = key;this.config = {type:"soql", query:"SELECT "

+ this.fieldlist.join(",")+ " FROM User"+ " WHERE Name like '" + key + "%'"+ " ORDER BY Name "+ " LIMIT 25 "

};}

});</script>

例: 次に、完全なモデルコードを示します。<script>

// The Models

// The User Modelapp.models.User = Force.SObject.extend({

sobjectType: "User",fieldlist: ["Id", "FirstName", "LastName",

"SmallPhotoUrl", "Title", "Email","MobilePhone","City"]

});

// The UserCollection Modelapp.models.UserCollection = Force.SObjectCollection.extend({

model: app.models.Userfieldlist: ["Id", "FirstName", "LastName",

"SmallPhotoUrl", "Title"],

getCriteria: function() {return this.key;

},

setCriteria: function(key) {this.key = key;

298

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

this.config = {type:"soql",query:"SELECT " + this.fieldlist.join(",")+ " FROM User"+ " WHERE Name like '" + key + "%'"+ " ORDER BY Name "+ " LIMIT 25 "

};}

});</script>

ビューテンプレートの作成テンプレートを使用すると、コンテナの HTML ページ内に HTML レイアウトを設定できます。HTML ページにインラインテンプレートを定義するには、タイプが「text/template」の <script> タグを使用します。JavaScript

コードでは、実行時に新しい HTML ページをインスタンス化する場合、テンプレートをページの設計に適用できます。search-page は、単純なテンプレートです。このテンプレートには、ヘッダー、検索項目、および検索結果を保持するリストが含まれます。検索ページでは、実行時に user-list-item テンプレートがインスタンス化されて、結果リストが表示されます。顧客がリスト項目をクリックすると、リストで user-page テンプレートがインスタンス化されてユーザの詳細が表示されます。1. ID が「search-page」に設定されたテンプレートスクリプトブロックを追加します。<body> ブロック内の

「content」<div> タグの直後にこのブロックを配置します。<script id="search-page" type="text/template"></script>

2. 新しい <script>ブロックで、Ratchet スタイルを使用して検索ページの HTML テンプレートを定義します。<script id="search-page" type="text/template"><header class="bar-title"><h1 class="title">Users</h1>

</header>

<div class="bar-standard bar-header-secondary"><input type="search" class="search-key"

placeholder="Search"/></div>

<div class="content"><ul class="list"></ul>

</div></script>

3. ユーザリストテンプレートの 2 番目のスクリプトブロックを追加します。<script id="user-list-item" type="text/template"></script>

299

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

4. ユーザリストテンプレートを定義します。このテンプレートには、Salesforce ユーザレコードのSmallPhotoUrl、FirstName、LastName、Title 項目への参照が含まれています。<%= varname %>

の形式を使用する参照は、Ratchet アプリケーションでは「自由変数」と呼ばれます。<script id="user-list-item" type="text/template"><a href="#users/<%= Id %>" class="pad-right"><img src="<%= SmallPhotoUrl %>" class="small-img" /><div class="details-short"><b><%= FirstName %> <%= LastName %></b><br/>Title<%= Title %>

</div></a>

</script>

5. ユーザ詳細テンプレートの 3 番目のスクリプトブロックを追加します。<script id="user-page" type="text/template"></script>

6. テンプレート本文を追加します。このテンプレートには、Salesforce ユーザレコードの SmallPhotoUrl、FirstName、LastName、Title項目への参照が含まれています。Ratchet アプリケーションで <%= varname

%> の形式を使用する参照は、「自由変数」と呼ばれます。<script id="user-page" type="text/template"><header class="bar-title"><a href="#" class="button-prev">Back</a><h1 class="title">User</h1>

</header>

<footer class="bar-footer"><span id="offlineStatus"></span>

</footer>

<div class="content"><div class="content-padded"><img id="employeePic" src="<%= SmallPhotoUrl %>"

class="large-img" /><div class="details"><b><%= FirstName %> <%= LastName %></b><br/><%= Id %><br/><% if (Title) { %><%= Title %><br/><% } %><% if (City) { %><%= City %><br/><% } %><% if (MobilePhone) { %> <a

href="tel:<%= MobilePhone %>"><%= MobilePhone %></a><br/><% } %>

<% if (Email) { %><ahref="mailto:<%= Email %>"><%= Email %></a><% } %>

</div></div>

</div></script>

300

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

検索ビューの追加画面のビューを作成するには、Backbone.Viewを拡張します。まず、検索ビューの定義から始めましょう。この拡張で、テンプレートの読み込み、サブビューとイベントハンドラの定義、およびビューを表示して SOQL

検索クエリを実行する機能の実装を行います。1. User および UserCollection モデルを定義した <script> ブロックで、SearchPage という名前の

Backbone.View 拡張を app.views 配列に作成します。app.views.SearchPage = Backbone.View.extend({});

この手順の残りの部分で、すべてのコードを extend({})ブロックに追加します。各ステップで別の項目を実装リストに追加するため、最後の項目まで末尾はカンマになります。

2. _.template() 関数をコールして search-page テンプレートを読み込みます。これに search-page スクリプトタグの未加工の HTML コンテンツを渡します。template: _.template($("#search-page").html()),

3. keyup イベントを追加します。search ハンドラ関数はもう少し後で定義します。events: {

"keyup .search-key": "search"},

4. 検索結果のリストを格納する UserListView という名前のサブビューをインスタンス化します。後でapp.views.UserListView を定義します。initialize: function() {

this.listView = new app.views.UserListView({model: this.model});},

5. 検索ページビューの render()関数を作成します。アプリケーションの HTML コンテンツとしてテンプレートを読み込んでビューを表示できます。検索項目に以前に入力した条件を復元し、<ul>要素内のサブビューを表示します。render: function(eventName) {

$(this.el).html(this.template());$(".search-key", this.el).val(this.model.getCriteria());this.listView.setElement($("ul", this.el)).render();return this;

},

6. search 関数を実装します。この関数は、顧客が検索項目に文字を入力したときに検索を実行する keyup

イベントハンドラです。search: function(event) {

this.model.setCriteria($(".search-key", this.el).val());this.model.fetch();

}

301

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

例: 次に、完全な拡張を示します。

app.views.SearchPage = Backbone.View.extend({

template: _.template($("#search-page").html()),

events: {

"keyup .search-key": "search"

},

initialize: function() {

this.listView = new app.views.UserListView({model: this.model});

},

render: function(eventName) {

$(this.el).html(this.template());

$(".search-key", this.el).val(this.model.getCriteria());

this.listView.setElement($("ul", this.el)).render();

return this;

},

search: function(event) {

this.model.setCriteria($(".search-key", this.el).val());

this.model.fetch();

}

});

検索結果リストビューの追加検索結果リストのビューでは、テンプレートは必要ありません。これは、単純にリスト項目ビューのコンテナです。listItemViewsメンバーのこれらのビューを追跡します。基盤となるコレクションが変更されると、それ自体を再表示します。1. SearchPage ビューを含む <script> ブロックで、Backbone.View を拡張して検索ビューの結果のリス

トを表示します。リスト項目ビューの配列と initialize() 関数を追加します。app.views.UserListView = Backbone.View.extend({

listItemViews: [],initialize: function() {

this.model.bind("reset", this.render, this);},

この手順の残りの部分で、すべてのコードを extend({}) ブロックに追加します。

2. render()関数を作成します。この関数は、既存の各リスト項目ビューで close()をコールしてこれらをクリーンアップします。render: function(eventName) {

_.each(this.listItemViews,function(itemView) { itemView.close(); });

302

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

3. render()関数で、基盤となるコレクションのレコードに対応する一連のリスト項目ビューを作成します。これらの各ビューは、リストのエントリにすぎません。後で app.views.UserListItemViewを定義します。this.listItemViews = _.map(this.model.models, function(model) { return new

app.views.UserListItemView({model: model}); });

4. render()関数で、各リスト項目ビューをルート DOM 要素に追加し、表示される UserListViewオブジェクトを返します。$(this.el).append(_.map(this.listItemViews, function(itemView) {

return itemView.render().el;} ));return this;

}

例: 次に、完全な拡張を示します。app.views.UserListView = Backbone.View.extend({

listItemViews: [],

initialize: function() {this.model.bind("reset", this.render, this);

},render: function(eventName) {

_.each(this.listItemViews, function(itemView) {itemView.close(); });

this.listItemViews = _.map(this.model.models,function(model) {

return new app.views.UserListItemView({model: model}); });

$(this.el).append(_.map(this.listItemViews,function(itemView) {

return itemView.render().el;} ));

return this;}

});

検索結果リスト項目ビューの追加検索結果リスト項目ビューを定義するには、リストの 1 行のビューを設計して実装します。各リスト項目には、次のユーザ項目が表示されます。• SmallPhotoUrl

• FirstName

• LastName

• 役職

303

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

1. UserListViewビュー定義の直後に、検索結果リスト項目のビューを作成します。再度、Backbone.View

を拡張し、tagNameメンバーを定義して、このビューがリスト項目であることを指定します。この手順の残りの部分で、すべてのコードを extend({}) ブロックに追加します。app.views.UserListItemView = Backbone.View.extend({

});

2. <li> タグを追加します。app.views.UserListItemView = Backbone.View.extend({

tagName: "li",});

3. user-list-item スクリプトの未加工のコンテンツを使用して _.template() をコールし、テンプレートを読み込みます。template: _.template($("#user-list-item").html()),

4. render() 関数を追加します。underscore.js の template() 関数は、JSON データを取得して、関連付けられているテンプレートから作成された HTML を返します。この例では、関数は JSON から顧客のデータを抽出し、user-list-itemテンプレートに適合する HTML を返します。HTML への変換時に、template()

関数は、テンプレートの自由変数を JSON データの対応するプロパティに置き換えます。render: function(eventName) {

$(this.el).html(this.template(this.model.toJSON()));return this;

},

5. リストビューからコールされる close()メソッドを追加し、必要なクリーンアップを行ってメモリリークを防止します。close: function() {

this.remove();this.off();

}

例: 次に、完全な拡張を示します。app.views.UserListItemView = Backbone.View.extend({

tagName: "li",template: _.template($("#user-list-item").html()),render: function(eventName) {

$(this.el).html(this.template(this.model.toJSON()));return this;

},close: function() {

this.remove();this.off();

}});

304

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

ユーザビューの追加最後に、選択した顧客の詳細を表示する単純なページビューを追加します。このビューは、このアプリケーションの 2 番目のページです。顧客は、ユーザリストビューの項目をタップしてこのビューに移動します。user-page テンプレートでは、検索リストに戻る [戻る] ボタンが定義されています。1. UserListItemViewビュー定義の直後に、顧客の詳細のビューを作成します。Backbone.Viewを再度拡

張します。この手順の残りの部分で、すべてのコードを extend({}) ブロックに追加します。app.views.UserPage = Backbone.View.extend({

});

2. インスタンス化するテンプレートを指定します。app.views.UserPage = Backbone.View.extend({

template: _.template($("#user-page").html()),});

3. render()関数を実装します。この関数は、モデルを再度読み取り、JSON に変換してから HTML に変換します。app.views.UserPage = Backbone.View.extend({

template: _.template($("#user-page").html()),

render: function(eventName) {$(this.el).html(this.template(this.model.toJSON()));return this;

}});

例: 次に、完全な拡張を示します。app.views.UserPage = Backbone.View.extend({

template: _.template($("#user-page").html()),render: function(eventName) {

$(this.el).html(this.template(this.model.toJSON()));return this;

}});

ルータの定義Backbone ルータは、ビュー間の移動パスを定義します。ルータについての詳細は、「ルータとは?」を参照してください。1. 最後の <script> ブロックで、Backbone.StackRouter を拡張してアプリケーションルータを定義しま

す。app.Router = Backbone.StackRouter.extend({

});

305

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

この手順の残りの部分で、すべてのコードを extend({}) ブロックに追加します。

2. アプリケーションでは検索リストページおよびユーザページがサポートされているため、各ページのルートを routes オブジェクト内に追加します。また、メインコンテナページ ("") のルートも追加します。routes: {

"": "list","list": "list","users/:id": "viewUser"

},

3. 検索結果のコレクション、検索ページビュー、およびユーザページビューを作成する initialize()関数を定義します。initialize: function() {

Backbone.Router.prototype.initialize.call(this);

// Collection behind search screenapp.searchResults = new app.models.UserCollection();

app.searchPage = new app.views.SearchPage({model: app.searchResults});

app.userPage = new app.views.UserPage();},

4. このルートの項目のみを処理する list() 関数を定義します。検索結果ページをすぐに表示するためにslidePage() をコールします。データを受信すると、リストが再作成されます。list: function() {

app.searchResults.fetch();this.slidePage(app.searchPage);

},

5. 特定のユーザの詳細を取得および表示する viewUser() 関数を定義します。viewUser: function(id) {

var that = this;var user = new app.models.User({Id: id});user.fetch({

success: function() {app.userPage.model = user;that.slidePage(app.userPage);

}});

}

6. アプリケーションを実行します。

例: これで完了です。次に、アプリケーション全体を示します。<!DOCTYPE html><html><head><title>Users</title>

306

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=no;" /><link rel="stylesheet" href="css/styles.css"/><link rel="stylesheet" href="css/ratchet.css"/></head>

<body>

<div id="content"></div>

<script src="js/jquery.min.js"></script><script src="js/underscore-min.js"></script><script src="js/backbone-min.js"></script><script src="js/forcetk.mobilesdk.js"></script>

<!-- Local Testing -/-><script src="js/forcetk.ui.js"></script><script src="js/MockCordova.js"></script><script src="js/cordova.force.js"></script><script src="js/MockSmartStore.js"></script><!-- End Local Testing -->

<!-- Container --><script src="cordova.js"></script><!-- End Container -->

<script src="js/smartsync.js"></script><script src="js/fastclick.js"></script><script src="js/stackrouter.js"></script><script src="js/auth.js"></script>

<!-- ----Search page template ---- --><script id="search-page" type="text/template"><header class="bar-title"><h1 class="title">Users</h1>

</header>

<div class="bar-standard bar-header-secondary"><input type="search"class="search-key"placeholder="Search"/>

</div>

<div class="content"><ul class="list"></ul>

</div></script>

<!-- ---- User list item template ---- --><script id="user-list-item" type="text/template">

<a href="#users/<%= Id %>" class="pad-right"><img src="<%= SmallPhotoUrl %>" class="small-img" />

307

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

<div class="details-short"><b><%= FirstName %> <%= LastName %></b><br/>Title<%= Title %>

</div></a>

</script>

<!-- ---- User page template ---- --><script id="user-page" type="text/template"><header class="bar-title"><a href="#" class="button-prev">Back</a><h1 class="title">User</h1>

</header>

<footer class="bar-footer"><span id="offlineStatus"></span>

</footer>

<div class="content"><div class="content-padded"><img id="employeePic"

src="<%= SmallPhotoUrl %>" class="large-img" /><div class="details"><b><%= FirstName %> <%= LastName %></b><br/><%= Id %><br/><% if (Title) { %><%= Title %><br/><% } %><% if (City) { %><%= City %><br/><% } %><% if (MobilePhone) { %>

<a href="tel:<%= MobilePhone %>"><%= MobilePhone %></a><br/><% } %>

<% if (Email) { %><a href="mailto:<%= Email %>"><%= Email %></a><% } %>

</div></div>

</div></script>

<script>// ---- The Models ---- //// The User Modelapp.models.User = Force.SObject.extend({

sobjectType: "User",fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl",

"Title", "Email", "MobilePhone","City"]});

// The UserCollection Modelapp.models.UserCollection = Force.SObjectCollection.extend({

model: app.models.User,fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl",

"Title"],

getCriteria: function() {

308

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

return this.key;},

setCriteria: function(key) {this.key = key;this.config = {type:"soql",

query:"SELECT "+ this.fieldlist.join(",")+ " FROM User"+ " WHERE Name like '" + key + "%'"+ " ORDER BY Name "+ " LIMIT 25 "

};}

});

// -------------------------------------------------- The Views---------------------------------------------------- //

app.views.SearchPage = Backbone.View.extend({

template: _.template($("#search-page").html()),

events: {"keyup .search-key": "search"

},

initialize: function() {this.listView =

new app.views.UserListView({model: this.model});

},

render: function(eventName) {$(this.el).html(this.template());$(".search-key", this.el).val(this.model.getCriteria());this.listView.setElement($("ul", this.el)).render();return this;

},

search: function(event) {this.model.setCriteria($(".search-key", this.el).val());this.model.fetch();

}});

app.views.UserListView = Backbone.View.extend({

listItemViews: [],

initialize: function() {this.model.bind("reset", this.render, this);

},

309

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

render: function(eventName) {_.each(this.listItemViews,

function(itemView) {itemView.close(); });this.listItemViews =

_.map(this.model.models, function(model) {return new app.views.UserListItemView(

{model: model}); });$(this.el).append(_.map(this.listItemViews,

function(itemView) {return itemView.render().el;} ));

return this;}

});

app.views.UserListItemView = Backbone.View.extend({

tagName: "li",template: _.template($("#user-list-item").html()),

render: function(eventName) {$(this.el).html(this.template(this.model.toJSON()));return this;

},

close: function() {this.remove();this.off();

}});

app.views.UserPage = Backbone.View.extend({

template: _.template($("#user-page").html()),

render: function(eventName) {$(this.el).html(this.template(this.model.toJSON()));return this;

}

});

// ----------------------------------------------- The Application Router------------------------------------------ //

app.Router = Backbone.StackRouter.extend({

routes: {"": "list","list": "list","users/:id": "viewUser"

},

310

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

initialize: function() {Backbone.Router.prototype.initialize.call(this);

// Collection behind search screenapp.searchResults = new app.models.UserCollection();

// We keep a single instance of SearchPage and UserPageapp.searchPage = new app.views.SearchPage(

{model: app.searchResults});app.userPage = new app.views.UserPage();

},

list: function() {app.searchResults.fetch();// Show page right away// List will redraw when data comes inthis.slidePage(app.searchPage);

},

viewUser: function(id) {var that = this;var user = new app.models.User({Id: id});user.fetch({

success: function() {app.userPage.model = user;that.slidePage(app.userPage);

}});

}});</script></body></html>

SmartSync サンプルアプリケーションSalesforce Mobile SDK には、ハイブリッドアプリケーションでの SmartSync の使用方法を示すサンプルアプリケーションが備えられています。Account Editor には、これらのサンプルの全機能が装備されています。いずれかの単純なサンプルに切り替えるには、bootconfig.json ファイルの startPage プロパティを変更します。

iOS でのサンプルの実行Salesforce Mobile SDK for iOS インストールディレクトリで、SalesforceMobileSDK.xcworkspace をダブルクリックして Xcode で開きます。Xcode プロジェクトナビゲータで、Hybrid SDK/AccountEditor プロジェクトを選択し、[Run (実行)] をクリックします。

311

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

Android でのサンプルの実行Android Studioでサンプルを実行するには、最初に SalesforceMobileSDK-Android リポジトリのコピーから基本ライブラリへの参照を追加します。次の連動関係をサンプルモジュールに追加し、それぞれの [Scope (範囲)] を「Compile」に設定します。• libs/SalesforceSDK

• libs/SmartStore

• hybrid/SampleApps/AccountEditor

Android Studio での作成が完了したら、ツールバーまたはメニューで [Run ‘<sample_name>’ (「<sample_name>」を実行)] をクリックします。

Account Editor のサンプルAccount Editor は、Mobile SDK 2.0 の最も複雑な SmartSync ベースのサンプルアプリケーションです。取引先をオンラインまたはオフラインで作成/編集/削除したり、競合の検出を示したりすることができます。サンプルを実行する手順は、次のとおりです。1. external/shared/sampleApps/smartsync/bootconfig.json に変更を加えた場合は、元のコンテン

ツに戻します。2. Account Editor を起動します。このアプリケーションには、3 つの画面が含まれています。• 取引先の検索• 取引先の詳細• 同期アプリケーションを初めて起動すると、最後に使用した取引先をリストする取引先検索画面が表示されます。この画面では、次の操作を実行できます。• 検索文字列を入力して、指定した文字列が名前に含まれている取引先を検索する。• 取引先をタップして、取引先詳細画面を起動する。• [作成] をタップして、空の取引先詳細画面を起動する。• [オンライン]をタップして、オフラインにする。すでにオフラインになっている場合は、[オフライン]ボタ

ンをタップして、オンラインに戻すことができます (デバイスを機内モードにして、オフラインにすることもできます)。

取引先詳細画面を起動するには、取引先検索画面で取引先レコードをタップします。選択した取引先の項目が、詳細画面に表示されます。この画面では、次の操作を実行できます。• 項目をタップして、値を変更する。• [保存] をタップして、取引先を更新または作成する。入力規則エラーが発生すると、問題のある項目が強

調表示されます。保存時にオンラインになっており、最後の取得以降にサーバのレコードが変更された場合は、リモートで変更された項目について警告が表示されます。[マージ]および [上書き]という他の 2 つのボタンを使用して、アプリケーションで変更をどのように保存するかを制御できます。[上書き] をタップすると、画面に現在表示されているすべての値がサーバに保存さ

312

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

れます。[マージ] をタップすると、ユーザが変更した項目のみがサーバに保存され、ユーザが変更しない項目についてはサーバで変更が継続されます。

• [削除] をタップして、取引先を削除する。• [オンライン] をタップしてオフラインにするか、[オフライン] をタップしてオンラインにする。同期画面を表示するには、[オンライン]をタップしてオフラインにしてから、取引先を作成、更新、または削除します。[オフライン]を再度タップしてオンラインに戻すと、デバイスで変更したすべての取引先が同期画面に表示されます。ローカルの変更をサーバに保存するには、[n 件のレコードを処理] をタップします。取引先の保存に失敗すると、同期に失敗したことが表記されて取引先がリストに残ります。リスト内の任意の取引先をタップしてさらに編集したり、ローカルで削除した取引先を復元したりできます。

内部で実行される処理の確認このサンプルのソースコードを表示するには、HTML またはテキストエディタで AccountEditor.html を開きます。ファイルの主要なセクションは、次のとおりです。• スクリプトの内容• テンプレート• モデル• ビュー• ルータ

スクリプトの内容このサンプルには、SmartSync アプリケーション用のライブラリの標準リストが含まれています。• jQuery — http://jquery.com/ を参照してください。• Underscore — Backbone に必要な JavaScript 用のユーティリティ関連のライブラリです。http://underscorejs.org/を

参照してください。• Backbone — Web アプリケーションに構造を提供します。SmartSync Data Framework で使用されます。

http://backbonejs.org/ を参照してください。• cordova.js — Salesforce Mobile SDK を使用するハイブリッドアプリケーションに必要です。• forcetk.mobilesdk.js — REST API コールを行うための Force.com JavaScript ライブラリです。SmartSync に必

要です。• smartsync.js — Mobile SDK SmartSync Data Framework です。• fastclick.js — 物理タップしてからクリックイベントが発生するまでの 300 ミリ秒の遅延を回避するた

めに使用されるライブラリです。https://github.com/ftlabs/fastclick を参照してください。• stackrouter.js および auth.js — 3 つのすべてのサンプルアプリケーションで使用されるヘルパー

JavaScript ライブラリです。

313

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

テンプレートこのアプリケーションのテンプレートは、次のとおりです。• search-page

• sync-page

• account-list-item

• edit-account-page (取引先詳細ページ用)

モデルこのアプリケーションでは、AccountCollection、Account および OfflineTracker という 3 つのモデルが定義されます。AccountCollection は SmartSync の Force.SObjectCollection クラスのサブクラスであり、Force.SObjectCollection は Backbone フレームワークの Collection クラスのサブクラスです。AccountCollection.config() メソッドは、コレクションに対する適切なクエリを返します。クエリモードには、次のいずれかを指定できます。• オンラインでありクエリ条件を指定していない場合は、最後に使用 (MRU)

• オンラインでありクエリ条件を指定した場合は SOQL

• オフラインの場合は SmartSQL

コレクションでアプリケーションから fetch()をコールすると、config()から返されたクエリが fetch()

関数で実行されます。このクエリ結果を使用して、オフラインキャッシュまたはサーバのいずれかの Account

オブジェクトで AccountCollection が入力されます。AccountCollection では、AccountEditor アプリケーションで設定された 2 つのグローバルキャッシュを使用します。app.cacheはオフラインストレージ用で、app.cacheForOriginalsは競合検出用です。コードでは、AccountCollection モデルが次のように指定されていることがわかります。• app.models.Account モデルのオブジェクトを含む (model 項目)

• クエリ対象の項目のリストを指定する (fieldlist 項目)

• サンプルアプリケーションのグローバルオフラインキャッシュを使用する (cache 項目)

• サンプルアプリケーションのグローバル競合検出キャッシュを使用する (cacheForOriginals 項目)

• オンラインクエリおよびオフラインクエリを処理する config() 関数を定義する次にコードを示します (読みやすくするため簡略化しています)。app.models.AccountCollection = Force.SObjectCollection.extend({

model: app.models.Account,fieldlist: ["Id", "Name", "Industry", "Phone", "Owner.Name",

"LastModifiedBy.Name", "LastModifiedDate"],cache: function() { return app.cache},cacheForOriginals: function() {

return app.cacheForOriginals;},

config: function() {// Offline: do a cache queryif (!app.offlineTracker.get("isOnline")) {

// ...

314

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

}// Onlineelse {

// ...}

}});

Account は SmartSync の Force.SObject クラスのサブクラスであり、Force.SObject は Backbone フレームワークの Modelクラスのサブクラスです。Accountモデルのコードは、次のように指定していることを示します。• sobjectType 項目を使用して、モデルが表す sObject の種別を示す (この場合は Account)。• サーバから取得する項目がサーバに送信する項目と同じではないため、fieldlistを項目としてではなく

メソッドとして定義する。• サンプルアプリケーションのグローバルオフラインキャッシュを使用する (cache 項目)。• サンプルアプリケーションのグローバル競合検出キャッシュを使用する (cacheForOriginals 項目)。• 現在のオフライン状況に基づいたキャッシュ方法を示す値を返す cacheMode()メソッドをサポートする。次にコードを示します。app.models.Account = Force.SObject.extend({

sobjectType: "Account",fieldlist: function(method) {

return method == "read"? ["Id", "Name", "Industry", "Phone", "Owner.Name",

"LastModifiedBy.Name", "LastModifiedDate"]: ["Id", "Name", "Industry", "Phone"];

},cache: function() { return app.cache;},cacheForOriginals: function() { return app.cacheForOriginals;},cacheMode: function(method) {

if (!app.offlineTracker.get("isOnline")) {return Force.CACHE_MODE.CACHE_ONLY;

}// Onlineelse {

return (method == "read" ?Force.CACHE_MODE.CACHE_FIRST :Force.CACHE_MODE.SERVER_FIRST);

}}

});

OfflineTracker は、Backbone の Model クラスのサブクラスです。このクラスは、ブラウザのオフライン状況を監視することによって、アプリケーションのオフライン状況を追跡します。ブラウザがオフラインであることが検出された場合は、アプリケーションが自動的にオフラインに切り替わります。ただし、オンラインになるのはユーザが要求した場合のみです。次にコードを示します。app.models.OfflineTracker = Backbone.Model.extend({

initialize: function() {

315

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

var that = this;this.set("isOnline", navigator.onLine);document.addEventListener("offline", function() {

console.log("Received OFFLINE event");that.set("isOnline", false);

}, false);document.addEventListener("online", function() {

console.log("Received ONLINE event");// User decides when to go back online

}, false);}

});

ビューこのサンプルでは、5 つのビューが定義されます。• SearchPage

• AccountListView

• AccountListItemView

• EditAccountView

• SyncPage

ビューには通常、デザインテンプレート、initialize()関数、および render()関数を指定するテンプレート項目が含まれています。各ビューでは、events項目も定義できます。この項目には配列が含まれ、キー/値エントリがイベントタイプおよびイベントハンドラ関数名をそれぞれ指定します。エントリには次の形式が使用されます。"<event-type>[ <control>]": "<event-handler-function-name>"

次に例を示します。events: {

"click .button-prev": "goBack","change": "change","click .save": "save","click .merge": "saveMerge","click .overwrite": "saveOverwrite","click .toggleDelete": "toggleDelete"

},

SearchPage

検索画面全体のビュー。モデルとして AccountCollectionが指定されます。検索入力項目に変更があるかどうか (keyup イベント) を監視し、search() 関数でモデルを適宜更新します。events: {

"keyup .search-key": "search"},search: function(event) {

this.model.setCriteria($(".search-key", this.el).val());this.model.fetch();

}

316

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

AcountListView

検索画面のリスト部分のビュー。モデルとして AccountCollection が指定され、AccountCollection

オブジェクトの取引先ごとに AccountListItemView オブジェクトが作成されます。AccountListItemView

リスト内の項目のビュー。EditAccountPage

取引先詳細ページのビュー。このビューでは、いくつかのイベントを監視します。

ハンドラ関数名ターゲットコントロールイベントタイプ

goBackbutton-prevクリックchangeset 以外 (任意の編集コントロール

が有効)

変更

savesaveクリックsaveMergemergeクリックsaveOverwriteoverwriteクリックtoggleDeletetoggleDeleteクリック

2 つのイベントハンドラ関数は、特に注意が必要です。change()関数は、ユーザ編集をモデルに戻すためにビューでイベントターゲットがどのように使用されるかを表示します。change: function(evt) {

// apply change to modelvar target = event.target;this.model.set(target.name, target.value);$("#account" + target.name + "Error", this.el).hide();

}

toggleDelete()関数は、ユーザが取引先を削除または復元できる切り替えを処理します。ユーザが復元をクリックした場合は、内部の __locally_deleted__ flag が false に設定され、レコードがキャッシュ内に復元されていることを示します。それ以外の場合は、ローカルモデルを破棄することによって、サーバでのレコードの削除が試みられます。toggleDelete: function() {

if (this.model.get("__locally_deleted__")) {this.model.set("__locally_deleted__", false);this.model.save(null, this.getSaveOptions(

null, Force.CACHE_MODE.CACHE_ONLY));}else {

this.model.destroy({success: function(data) {

app.router.navigate("#", {trigger:true});},error: function(data, err, options) {

var error = new Force.Error(err);

317

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

alert("Failed to delete account:" + (error.type === "RestError" ?

error.details[0].message :"Remote change detected - delete aborted"));

}});

}}

SyncPage

同期ページのビュー。このビューでは、いくつかのイベントを監視します。

ハンドラ関数名コントロールイベントタイプ

goBackbutton-prevクリックsyncsyncクリック

画面がどのように表示されるかを確認するには、render メソッドを調べます。render: function(eventName) {

$(this.el).html(this.template(_.extend({countLocallyModified: this.model.length},this.model.toJSON())));

this.listView.setElement($("ul", this.el)).render();

return this;

},

ユーザが [実行] (同期コントロール) をタップしたときの動作を見てみましょう。sync() 関数は、まずローカルで変更された取引先をビューのコレクションで確認し、それをサーバに保存しようとします。保存に成功し、ローカルで変更された他のレコードがない場合は、アプリケーションが検索画面に戻ります。それ以外の場合は、取引先がローカルの保存に失敗したとマークされ、sync()

を再度コールします。sync: function(event) {

var that = this;if (this.model.length == 0 ||

this.model.at(0).get("__sync_failed__")) {// We push sync failures back to the end of the list.// If we encounter one, it means we are done.return;

}else {

var record = this.model.shift();

var options = {mergeMode: Force.MERGE_MODE.MERGE_FAIL_IF_CHANGED,success: function() {

318

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

if (that.model.length == 0) {app.router.navigate("#", {trigger:true});

}else {

that.sync();}

},error: function() {

record = record.set("__sync_failed__", true);that.model.push(record);that.sync();

}};return record.get("__locally_deleted__")

? record.destroy(options) :record.save(null, options);

}});

ルータルータが初期化されると、サンプル全体で使用される 2 つグローバルキャッシュが設定されます。setupCaches: function() {

// Cache for offline supportapp.cache = new Force.StoreCache("accounts",

[ {path:"Name", type:"string"} ]);

// Cache for conflict detectionapp.cacheForOriginals = new Force.StoreCache("original-accounts");

return $.when(app.cache.init(), app.cacheForOriginals.init());},

グローバルキャッシュが設定されると、2 つの AccountCollection オブジェクトも設定されます。1 つは検索画面用、もう 1 つは同期画面用です。// Collection behind search screenapp.searchResults = new app.models.AccountCollection();

// Collection behind sync screenapp.localAccounts = new app.models.AccountCollection();app.localAccounts.config = {

type:"cache",cacheQuery: {

queryType:"exact",indexPath:"__local__",matchKey:true,order:"ascending",pageSize:25}};

319

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

最後に、Search、Sync、および EditAccount の各画面用にビューオブジェクトが作成されます。// We keep a single instance of SearchPage / SyncPage and EditAccountPageapp.searchPage = new app.views.SearchPage({model: app.searchResults});app.syncPage = new app.views.SyncPage({model: app.localAccounts});app.editPage = new app.views.EditAccountPage();

ルータには、アクションをルータクラスのメソッドに対応付ける routes 項目があります。routes: {

"": "list","list": "list","add": "addAccount","edit/accounts/:id": "editAccount","sync":"sync"

},

listアクションは、fetch()をコールして検索結果のコレクションを取得し、検索ページをビューに表示します。list: function() {

app.searchResults.fetch();// Show page right away - list will redraw when data comes inthis.slidePage(app.searchPage);

},

addAccountアクションは、空の取引先オブジェクトを作成し、その取引先の編集ページをビューに表示します。addAccount: function() {

app.editPage.model = new app.models.Account({Id: null});this.slidePage(app.editPage);

},

editAccountアクションは、指定された Account オブジェクトを取得し、取引先詳細ページをビューに表示します。editAccount: function(id) {

var that = this;var account = new app.models.Account({Id: id});account.fetch({

success: function(data) {app.editPage.model = account;that.slidePage(app.editPage);

},error: function() {

alert("Failed to get record for edit");}

});}

sync アクションは、fetch をコールして localAccountsコレクションを計算し、同期ページをビューに表示します。sync: function() {

app.localAccounts.fetch();

320

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

// Show page right away - list will redraw when data comes inthis.slidePage(app.syncPage);

}

321

ハイブリッドアプリケーションでの SmartSync の使用オフライン管理

第 11 章 ファイルとネットワーキング

Mobile SDK には、2 つのレベルのテクノロジを実装するファイル管理の API が用意されています。Mobile SDK では、Chatter REST API を介してファイル要求を処理する便利

トピック:

• アーキテクチャ なファイル管理用のメソッドを提供します。ネットワーキングクラスにより、アプ• ファイルのダウン

ロードと共有の管理

リケーションを使用して REST API レベルで待機中の REST 要求を制御できます。このような表裏一体のテクノロジを合わせることで、堅牢なコンテンツ管理機能と高度なネットワーキングパフォーマンスを SDK で実現できます。

• ファイルのアップロード

• 暗号化とキャッシュ

• Android アプリケーションでのファイルの使用

• iOS ネイティブアプリケーションでのファイルの使用

• ハイブリッドアプリケーションでのファイルの使用

322

アーキテクチャ

Mobile SDK 4.2 以降では、Android REST 要求システムは、基盤となるアーキテクチャとして Square Open Source のオープンソース外部ライブラリの OkHttp (v3.2.0) を使用します。過去のリリースの Google Volley ライブラリは、このライブラリに置き換えられます。そのため、Mobile SDK では、WrappedRestRequestクラスが定義されなくなりました。詳細は、square.github.io/okhttp/を参照してください。iOS では、SalesforceNetwork ライブラリを使用して、ファイル管理およびネットワーキングを行います。ファイルや他の REST 要求の REST API コールは、すべてこのライブラリを経由します。

メモ: 古いバージョンのアプリケーションでサードパーティネットワーキングライブラリに直接アクセスした場合、SalesforceNetwork ライブラリを使用するようにそのコードを更新する必要があります。

ハイブリッド JavaScript 関数では、デバイスのオペレーティングシステム (Android、iOS、または Windows) に対応する Mobile SDK のアーキテクチャを使用して、ファイル操作を実装します。これらの関数は、forcetk.mobilesdk.js で定義されています。

ファイルのダウンロードと共有の管理

Salesforce Mobile SDK には、ファイルのダウンロード操作や共有操作のための特殊な REST 要求を構築する便利なメソッドがあります。これらの要求を使用して、次のことを実行できます。• ファイルのバイトストリームにアクセスする。• ファイルのページをダウンロードする。• ファイルのページをプレビューする。• ファイルレコードの詳細を取得する。• ファイル共有情報にアクセスする。• ファイル共有を追加および削除する。

要求のページREST 要求の「ページ」という用語は、コンテキストに応じて結果セットの特定項目または項目グループを表します。たとえば、特定のファイルのページをプレビューする場合、要求は表示されたページの中から指定されたページを取得します。他の大部分の要求では、ページとは結果のリストのセクションを表します。1 ページのレコードまたはトピックの最大数は、デフォルトの 25 に設定されます。応答には、NextPageUrl項目が含まれます。この値が定義されている場合、結果には別のページがあります。アプリケーションで結果のページをスクロールする場合、この項目を使用して不要な要求が送信されないようにできます。また、応答状況を確認するだけで、リストの最後であるかどうかを検出することもできます。何も返されない場合やエラーが返される場合は、これ以上表示するものがないため、別の要求を発行する必要はありません。

323

アーキテクチャファイルとネットワーキング

ファイルのアップロード

ネイティブモバイルプラットフォームでは、ファイルをアップロードするためのメソッドがサポートされています。アップロードするローカルファイルへのパス、ファイルの名前またはタイトル、および説明を入力します。MIME タイプがわかっている場合、そのタイプも指定できます。アップロードメソッドは、ファイルをサーバにアップロードできるプラットフォーム固有の要求オブジェクトを返します。この要求をサーバに送信すると、バージョンが 1 に設定されたファイルがサーバで作成されます。次に、アプリケーション種別ごとに使用するメソッドを示します。

署名Upload メソッドアプリケーション種別

public static RestRequestuploadFile(

FileRequests.uploadFile()Android ネイティブ

File theFile,String name,String description,String mimeType)throws UnsupportedEncodingException

- (SFRestRequest *)requestForUploadFile:(NSData *)data

- requestForUploadFile:name:description:mimeType:

iOS ネイティブ

name:(NSString *)namedescription:(NSString *)descriptionmimeType:(NSString *)mimeType

なしなしハイブリッド(Android と iOS)

暗号化とキャッシュ

Mobile SDK は、ファイルの暗号化されていないバイトストリームへのアクセスを提供しますが、ファイルのキャッシュまたは保存は実装しません。アプリケーションでファイルをデバイスに保存する必要がある場合、独自の解決策を自由に考案できます。

Android アプリケーションでのファイルの使用

FileRequestsクラスは、ファイル操作を実行する RestRequestオブジェクトを作成するための静的メソッドを提供します。各メソッドは、新しい RestRequestオブジェクトを返します。次に、アプリケーションはownedFilesList()メソッドをコールして RestRequestオブジェクトを取得します。このオブジェクトは、RestRequest オブジェクトを使用してサーバに要求を送信する関数にパラメータとして渡されます。performRequest(FileRequests.ownedFilesList(null, null));

324

ファイルのアップロードファイルとネットワーキング

この例では、null を最初のパラメータ (userId) に渡します。この値で、コンテキスト (ログインしている) ユーザの ID を使用するように ownedFilesList() メソッドに指示しています。pageNum パラメータの 2 番目のnull で、結果の最初のページを取得するようにメソッドに指示します。ネイティブ Android アプリケーションの場合、ファイル管理クラスおよびメソッドはcom.salesforce.androidsdk.rest.files パッケージにあります。

関連トピック:

FileRequests メソッド (Android)

要求キューの管理RestClient クラスは、内部的に OkHttpClient クラスのインスタンスを使用して REST API 要求を管理します。基盤となる OkHttp オブジェクトに直接アクセスして、待機中の要求をキャンセルできます。特定の要求を管理するには、RestClient.sendAsync() Mobile SDKメソッドによって返される OkHttp Callオブジェクトを使用します。

例: 次の例に、OkHttpClientを使用したいくつかの一般的なネットワーク操作の実行方法を示します。一般的なインポート

import okhttp3.Headers;

import okhttp3.HttpUrl;

import okhttp3.OkHttpClient;

import okhttp3.Call;

import okhttp3.Dispatcher;

import okhttp3.Request;

import okhttp3.RequestBody;

import okhttp3.Response;

現在の OkHttp クライアントハンドルを取得する現在の RestClient インスタンスが使用している OkHttpClient のハンドルを取得するには、次のように指定します。

OkHttpClient okClient = restClient.getOkHttpClient();

OkHttp ディスパッチャを取得する

Dispatcher dispatcher = restClient.getOkHttpClient().dispatcher();

待機中のすべてのコールをキャンセルする

Dispatcher dispatcher = restClient.getOkHttpClient().dispatcher();

dispatcher.cancelAll();

OkHttp ハンドルを REST 要求に格納する

Call call = restClient.sendAsync(restRequest, callback);

325

要求キューの管理ファイルとネットワーキング

格納されたハンドルを使用して特定の REST 要求をキャンセルする

Call call = restClient.sendAsync(restRequest, callback);

...

call.cancel();

詳細は、square.github.io/okhttp/を参照してください。

関連トピック:

OkHttp: 基盤となるネットワークライブラリ

iOS ネイティブアプリケーションでのファイルの使用

ネイティブ iOS アプリケーションでファイルを処理するには、SFRestAPI (Files) カテゴリで定義されている便利なメソッドを使用します。これらのメソッドは、Android ネイティブアプリケーションとハイブリッドアプリケーションの Files API と似ています。これらは、要求を REST API の同じリストに送信しますが、異なる基盤を使用します。

REST 応答とマルチスレッドSalesforceNetwork ライブラリは常に、現在 SFRestDelegate が実行されているスレッドに REST 応答を送ります。この設計では、代理メソッドでどのようにサーバ応答を処理しても、目的の用途に対応できます。応答を受信したら、返されたデータを使用して任意の操作を実行できます。たとえば、キャッシュしたり、データベースに保存したり、すぐに UI コントロールに一括送信したりできます。ただし、応答を直接 UI に送信する場合代理メソッドでそのメッセージをメインスレッドに送る必要があります。

関連トピック:

SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)

要求の管理iOS 用の SalesforceNetwork ライブラリでは、SFNetworkEngine と SFNetworkOperation の 2 つの主オブジェクトを定義します。SFRestRequest は、内部的に SFNetworkOperation オブジェクトを使用して、各サーバコールを実行します。要求のために SFNetworkOperation オブジェクトにアクセスする方法は 2 つあります。• 次のメソッドは SFNetworkOperation* を返します。

– [SFRestRequest send:]

– [SFRestAPI send:delegate:]

• SFRestRequest オブジェクトには、種別が SFNetworkOperation* の networkOperation オブジェクトが含まれます。

待機中の REST 要求をキャンセルする方法も 2 つあります。

326

iOS ネイティブアプリケーションでのファイルの使用ファイルとネットワーキング

• SFRestRequest は、要求をキャンセルする新しいメソッドを提供します。- (void) cancel;

• SFRestAPI には、現在実行されているすべての要求をキャンセルするメソッドがあります。- (void)cancelAllRequests;

例: 要求をキャンセルする方法の例

すべての要求をキャンセルする[[SFRestAPI sharedInstance] cancelAllRequests];

1 つの要求をキャンセルするSFRestRequest *request = [[SFRestAPI sharedInstance] requestForOwnedFilesList:nilpage:0];[[SFRestAPI sharedInstance] send:request delegate:self];...// User taps Cancel Request button while waiting for the response-(void) cancelRequest:(SFRestRequest *) request {

[request cancel];}

ハイブリッドアプリケーションでのファイルの使用

ハイブリッドファイル要求ラッパーは、forcetk.mobilesdk.js JavaScript ライブラリにあります。ハイブリッド関数を使用する場合、サーバ応答を受信して処理するコールバック関数を渡します。また、エラーを処理する関数も渡します。コードを簡素化するために、smartsync.js および forcetk.mobilesdk.js ライブラリを利用して、HTML

アプリケーションを構築できます。HybridFileExplorer サンプルアプリケーションは、この方法を示します。

メモ: Mobile SDK では、ハイブリッドアプリケーションでのファイルのアップロードをサポートしていません。

関連トピック:

ハイブリッドアプリケーションの Files メソッド

327

ハイブリッドアプリケーションでのファイルの使用ファイルとネットワーキング

第 12 章 転送通知と Mobile SDK

Salesforce からの転送通知は、モバイルユーザが組織内の重要な動向を常に把握しておくのに役立ちます。Summer '14 で正式リリースされた Salesforce Mobile 転送通知サー

トピック:

• 転送通知について ビスでは、コードを実装する前にモバイル転送通知を設定およびテストできます。• ハイブリッドアプ

リケーションでの転送通知の使用

本番環境でモバイル通知を受信するには、Mobile SDK アプリケーションでモバイルOS プロバイダの登録プロトコルを実装して、受信通知を処理します。Mobile SDK では、大部分の登録タスクが内部的に実装されているため、コーディング作業を最小限に抑えることができます。• Android での転送通

知の使用• iOS での転送通知の

使用

328

転送通知について

Salesforce Mobile 転送通知サービスを使用すると、Salesforce Mobile SDKアプリケーションで転送通知を開発してテストできます。Mobile SDKには、転送通知サービスへのデバイス登録を実装できる API が用意されています。ただし、通知の受信と処理は、引き続き開発者が行う必要があります。転送通知の設定は、さまざまなレベルで行われます。• デバイステクノロジプロバイダからの転送サービスの設定 (Apple for iOS、Google for Android)

• 転送通知を有効にするための Salesforce 接続アプリケーション定義の設定• Apex トリガの実装

またはChatter REST API の転送通知リソースのコール

• Mobile SDK アプリケーションでのコードの変更• 実行時のモバイルデバイスの登録Apple または Google のサービス設定、接続アプリケーションの設定、Apex または Chatter REST API のコーディング、およびMobile SDKアプリケーションへの軽微な変更は、お客様自身で行います。Salesforce Mobile SDKは、ランタイム登録を透過的に処理します。組織のモバイル転送通知の設定方法についての詳細は、「モバイル転送通知の概要」を参照してください。

ハイブリッドアプリケーションでの転送通知の使用

ハイブリッドアプリケーションで転送通知を使用するには、まず次のことを行います。• OS プロバイダの転送通知に登録する。• ターゲットデバイスプラットフォームの転送通知をサポートするように接続アプリケーションを設定する。Salesforce Mobile SDK では、ハイブリッドアプリケーション自体で通知を受信するように登録できます。登録したら、受信通知を処理する動作を定義します。

関連トピック:

Android での転送通知の使用iOS での転送通知の使用

コードの変更 (ハイブリッド)1. (Android のみ) 対象プラットフォームが Android の場合は、次の操作を実行します。

a. androidPushNotificationClientIdのエントリを追加します。assets/www/bootconfig.jsonの場合"androidPushNotificationClientId": "33333344444"

この値は、Android デバイスに対して転送通知の送信が承認された Google プロジェクトのプロジェクト番号です。

329

転送通知について転送通知と Mobile SDK

2. cordova.require("com.salesforce.plugin.oauth").getAuthCredentials()のコールバックに、次のコードを追加します。cordova.require("com.salesforce.util.push").registerPushNotificationHandler(

function(message) {// add code to handle notifications

},function(error) {

// add code to handle errors}

);

例: このコードは、メッセージの処理方法の一例を示しています。サーバは、message["payload"] のペイロードを配信します。function(message) {

var payload = message["payload"];if (message["foreground"]) {

// Notification is received while the app is in// the foreground// Do something appropriate with payload

}if (!message["foreground"]) {

// Notification was received while the app was in// the background, and the notification was clicked,// bringing the app to the foreground// Do something appropriate with payload

}}

Android での転送通知の使用

Salesforce では、Google Cloud Messaging for Android (GCM) フレームワークを介して転送通知が Android アプリケーションに送信されます。このフレームワークの概要については、http://developer.android.com/google/gcm/index.html を参照してください。転送通知をサポートする Android アプリケーションを開発する場合、次の重要な点に留意してください。• Android Developer Program のメンバーである必要があります。• GCM 転送サービスは、Android Market アプリケーションまたは Google Play サービスのいずれかがインストール

された Android デバイスでのみテストできます。転送通知は、Android エミュレータでは動作しません。• 接続アプリケーションの詳細ビューにある [テスト通知の送信] リンクを使用して、デバイスを ping するこ

となく GCM 設定の「模擬実行」テストを行うこともできます。まず、アプリケーションに Google API プロジェクトを作成します。プロジェクトでは、GCM for Android 機能が有効になっている必要があります。プロジェクトの設定手順については、http://developer.android.com/google/gcm/gs.html

を参照してください。Google API プロジェクトの設定プロセスでは、アプリケーションのキーが作成されます。プロジェクトの設定が完了したら、GCM キーを接続アプリケーションの設定に追加する必要があります。

330

Android での転送通知の使用転送通知と Mobile SDK

メモ: 転送通知の登録は、OAuth ログインフローの最後に行われます。そのため、ユーザが Salesforce 組織にログインするまで、転送通知はアプリケーションで受信されません。

GCM (Android) 用に接続アプリケーションを設定する転送通知をサポートするように Salesforce 接続アプリケーションを設定する手順は、次のとおりです。1. Salesforce組織で、[設定] から、[クイック検索]ボックスに「アプリケーション」と入力し、[アプリケーショ

ン] を選択します。2. [接続アプリケーション]で、既存の接続アプリケーションの横にある [編集]をクリックするか、[新規]をク

リックして新しい接続アプリケーションを作成します。+新しい接続アプリケーションを作成する場合は、「接続アプリケーションを作成する」を参照してください。

3. [モバイルアプリケーション設定] で、[プッシュメッセージングの有効化] を選択します。4. [サポートされているプッシュプラットフォーム] で [Android GCM] を選択します。5. [サーバアプリケーションのキー (API キー)] に、Google への開発者登録時に取得したキーを入力します。

6. [保存] をクリックします。

メモ: 新しい接続アプリケーションを保存したら、コンシューマ鍵を取得します。モバイルアプリケーションは、このキーを接続トークンとして使用します。

コードの変更 (Android)転送通知をサポートするように Mobile SDK アプリケーションを設定する手順は、次のとおりです。1. androidPushNotificationClientId のエントリを追加します。

• res/values/bootconfig.xml は次のようになります (ネイティブアプリケーションの場合)。<string name="androidPushNotificationClientId">33333344444</string>

• assets/www/bootconfig.json は次のようになります (ハイブリッドアプリケーションの場合)。"androidPushNotificationClientId": "33333344444"

この値は、Android デバイスに対して転送通知の送信が承認された Google プロジェクトのプロジェクト番号です。Mobile SDKはこの値を自動的に読み取り、それを使用して、Salesforce接続アプリケーションに対してデバイスを登録します。この検証により、Salesforce から接続アプリケーションに通知を送信できます。また、ログアウト時には転送通知用のデバイスが Mobile SDK で自動的に登録解除されます。

331

GCM (Android) 用に接続アプリケーションを設定する転送通知と Mobile SDK

2. PushNotificationInterface を実装するアプリケーションでクラスを作成します。PushNotificationInterface は、転送通知を処理するためのMobile SDK Android インターフェースです。PushNotificationInterfaceには、onPushMessageReceived(Bundle message)という 1 つのメソッドがあります。public interface PushNotificationInterface {

public void onPushMessageReceived(Bundle message);}

このメソッドでは、転送通知を表示または破棄するカスタム機能を実装します。

3. Application サブクラスの onCreate() メソッドで、PushNotificationInterface の実装を渡してSalesforceSDKManager.setPushNotificationReceiver() メソッドをコールします。SalesforceSDKManager.initNative() コールの直後に、このメソッドをコールします。次に例を示します。@Overridepublic void onCreate() {

super.onCreate();SalesforceSDKManager.initNative(getApplicationContext(),

new KeyImpl(), MainActivity.class);SalesforceSDKManager.getInstance().

setPushNotificationReceiver(myPushNotificationInterface);}

iOS での転送通知の使用

転送通知をサポートする iOS アプリケーションを開発する場合、次の重要な点に留意してください。• iOS Developer Program のメンバーである必要があります。• Apple 転送サービスは、iOS 物理デバイスでのみテストできます。転送通知は、iOS エミュレータでは動作し

ません。• 通知が Apple で受け入れられても、すべての転送通知が対象デバイスに到達するという保証はありません。• Apple Push Notification Services 設定では、Mac OS X で提供されている OpenSSL コマンドラインユーティリティを

使用する必要があります。Salesforce側で登録を完了する前に、Apple Push Notification Servicesに登録する必要があります。以下の手順では、必要な処理の概要を示します。完全な手順は、http://www.raywenderlich.com/32960/ を参照してください。

Apple Push Notification Services の設定Apple Push Notification Services (APNS) に登録するには、次のものが必要です。証明書署名要求 (CSR) ファイル

Mac OS X の Keychain Access 機能を使用して、この要求を生成します。また、後で使用するために、OpenSSL を使用して、CSR 秘密鍵をファイルにエクスポートします。

332

iOS での転送通知の使用転送通知と Mobile SDK

iOS Developer Program のアプリケーション ID

iOS Developer Member Center で、アプリケーションの ID を作成し、CSR ファイルを使用して証明書を生成します。次に、OpenSSL を使用して、この証明書と秘密鍵のファイルを組み合わせて .p12ファイルを作成します。このファイルは、接続アプリケーションを後で設定するときに必要になります。

iOS Provisioning Profile

iOS Developer Member Center から、iOS アプリケーション ID と開発者証明書を使用して新しいプロビジョニングプロファイルを作成します。次に、プロファイルに含めるデバイスを選択して、プロビジョニングプロファイルをダウンロードして作成します。このようにすると、プロファイルを Xcode に追加できます。Xcode

の Organizer を使用して、テストデバイスにプロファイルをインストールします。設定が完了したら、Xcode でアプリケーションに署名し、アプリケーションを作成します。アプリケーションで正しいプロビジョニングプロファイルが使用されていることを、作成ログで確認します。プロビジョニングプロファイルの内容を表示するには、ターミナルウィンドウでコマンド security cms -D -i <your

profile>.mobileprovision を実行します。

APNS (iOS) 用に接続アプリケーションを設定するApple Push Notification Services (APNS) を使用した転送通知をサポートするように Salesforce 接続アプリケーションを設定する手順は、次のとおりです。1. Salesforce組織で、[設定] から、[クイック検索]ボックスに「アプリケーション」と入力し、[アプリケーショ

ン] を選択します。2. [接続アプリケーション]で、既存の接続アプリケーションの横にある [編集]をクリックするか、[新規]をク

リックして新しい接続アプリケーションを作成します。+新しい接続アプリケーションを作成する場合は、「接続アプリケーションを作成する」を参照してください。

3. [モバイルアプリケーション設定] で、[プッシュメッセージングの有効化] を選択します。4. [サポートされているプッシュプラットフォーム]で [Apple] を選択します。

ページが展開されて、追加設定が表示されます。

5. APNS 証明書に対応する Apple 環境を選択します。6. [モバイルアプリケーション設定] > [証明書]および [モバイルアプリケーション設定] > [証明書のパスワード]

で、.p12 ファイルとそのパスワードを追加します。

333

APNS (iOS) 用に接続アプリケーションを設定する転送通知と Mobile SDK

メモ: Apple 環境、証明書、証明書のパスワードの値は、APNS でアプリケーションを設定するときに取得します。

7. [保存] をクリックします。

コードの変更 (iOS)Salesforce Mobile SDK for iOS には、転送登録を処理するための SFPushNotificationManager クラスが備えられています。これを使用するには、import <SalesforceSDKCore/SFPushNotificationManager>を実行します。SFPushNotificationManager クラスは、ランタイムシングルトンとして使用できます。[SFPushNotificationManager sharedInstance]

このクラスは、次の 4 つの登録メソッドを実装します。- (void)registerForRemoteNotifications;- (void)didRegisterForRemoteNotificationsWithDeviceToken:

(NSData*)deviceTokenData;- (BOOL)registerForSalesforceNotifications; // for internal use- (BOOL)unregisterSalesforceNotifications; // for internal use

Mobile SDK では、ログイン後に registerForSalesforceNotifications をコールし、ログアウト時にunregisterSalesforceNotifications をコールします。他の 2 つのメソッドは、AppDelegate クラスからコールします。

例: SFPushNotificationManager の例

転送通知をサポートするように AppDelegate クラスを設定する手順は、次のとおりです。1. registerForRemoteNotifications をコールして、Apple に転送通知を登録します。コールを

application:didFinishLaunchingWithOptions: メソッドに配置します。- (BOOL)application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

self.window =[[UIWindow alloc] initWithFrame:

[UIScreen mainScreen].bounds];[self initializeAppViewState];

//// Register with APNS for push notifications. Note that,

334

コードの変更 (iOS)転送通知と Mobile SDK

// to receive push notifications from Salesforce,// you also need to register for Salesforce notifications// in the application:// didRegisterForRemoteNotificationsWithDeviceToken:// method (as demonstrated below.)//[[SFPushNotificationManager sharedInstance]

registerForRemoteNotifications];

[[SFAuthenticationManager sharedManager]loginWithCompletion:self.initialLoginSuccessBlock

failure:self.initialLoginFailureBlock];

return YES;}

登録に成功すると、Apple から AppDelegate クラスのapplication:didRegisterForRemoteNotificationsWithDeviceToken: メソッドにデバイストークンが渡されます。

2. SFPushNotificationManager 共有インスタンスでdidRegisterForRemoteNotificationsWithDeviceToken をコールして、デバイストークンをApple から SFPushNotificationManager に転送します。- (void)application:(UIApplication*)application

didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken

{//// Register your device token// with the push notification manager//[[SFPushNotificationManager sharedInstance]

didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];

}

3. registerForSalesforceNotifications をコールして、接続アプリケーション経由で Salesforce 通知を受信するよう登録します。このコールは、現在のセッションのアクセストークンが有効な場合にのみ行います。- (void)application:(UIApplication*)application

didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken

{//// Register your device token with the// push notification manager//[[SFPushNotificationManager sharedInstance]

didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];

335

コードの変更 (iOS)転送通知と Mobile SDK

if ([SFAccountManager sharedInstance].credentials.accessToken != nil) {[[SFPushNotificationManager sharedInstance]

registerForSalesforceNotifications];}}

4. Apple への登録が失敗した場合にエラーをログ記録するために、次のメソッドを追加します。- (void)application:(UIApplication*)application

didFailToRegisterForRemoteNotificationsWithError:(NSError*)error{

NSLog(@"Failed to get token, error: %@", error);}

336

コードの変更 (iOS)転送通知と Mobile SDK

第 13 章 モバイルアプリケーションでの認証、セキュリティ、ID

モバイルデバイスで実行されているエンタープライズアプリケーションにとって、安全な認証は不可欠です。OAuth 2.0 は、ユーザのデータへのアクセスに対する安全

トピック:

• OAuth の用語 な認証を可能にする業界標準のプロトコルで、ユーザ名およびパスワードを渡す必• OAuth2.0 認証フ

ロー要がありません。OAuth は、ソフトウェアアクセスのバレットキーと呼ばれることがよくあります。バレットキーとは、自動車の特定の部分のみを開錠できる鍵のことで、トランクやダッシュボードの小物入れなどは開けることができません。• 接続アプリケー

ション モバイルアプリケーションの開発者は、Salesforce OAuth2.0 の実装をすばやく簡単に組み込むことができます。実装では HTML ビューを使用してユーザ名とパスワードが収• OAuth 2.0 サイトお

よび Force.com サイ 集され、それがサーバに送信されます。サーバからセッショントークンと永続更新トークンが返され、今後のやり取りのためにデバイスに保存されます。トを使用したポー

タル認証Salesforce 接続アプリケーションは、モバイルデバイスを Salesforce に接続するための主要な手段です。接続アプリケーションにより、開発者と管理者は、アプリケーショ

• Salesforce MobileSDK アプリケーションでの MDM の使用 ンの接続方法およびアクセス権を付与するユーザを制御できます。たとえば、接続

アプリケーションでアクセスを一連のユーザに制限したり、IP 範囲の設定または緩和などを行うことができます。

337

OAuth の用語

アクセストークンユーザの Salesforce ログイン情報を使用する代わりに、保護されたリソースへのユーザのアクセスを許可するためにコンシューマにより使用される値。アクセストークンはセッション ID であり、直接使用できます。

認証コードエンドユーザによって付与されるアクセスを表示する、有効期間の短いトークンです。認証コードは、アクセストークンと更新トークンを取得するために使用されます。

接続アプリケーションOAuth プロトコルを使用してSalesforceユーザと外部アプリケーションの両方を検証する、Salesforceの外部アプリケーションです。

コンシューマ鍵コンシューマ (この場合は、Mobile SDKアプリケーション) が Salesforceに自身の身分を証明するために使用する値です。client_id とも呼ばれます。

コンシューマの秘密コンシューマ鍵の所有権を確認するためにコンシューマにより使用される秘密。セキュリティを強化するため、Mobile SDK アプリケーションは、コンシューマの秘密を使用しません。

更新トークン新しいアクセストークンを取得するためにコンシューマが使用するトークン。エンドユーザがアクセスを再度承認する必要がありません。

リモートアクセスアプリケーション (廃止)

リモートアクセスアプリケーションとは、OAuth プロトコルを使用して Salesforce ユーザと外部アプリケーションの両方を検証する、Salesforceの外部アプリケーションです。リモートアクセスアプリケーションは、接続アプリケーションとして実装されています。リモートアクセスアプリケーションは廃止され、接続アプリケーションになりました。

OAuth2.0 認証フロー

認証フローは、デバイスにおける認証状態によって異なります。

初回の認証フロー1. モバイルアプリケーションを開きます。2. 認証ダイアログ/ウィンドウ/フロート表示が画面に表示されます。3. ユーザ名とパスワードを入力します。4. アプリケーションでセッション ID を受信します。5. アプリケーションへのアクセスを許可します。6. アプリケーションが起動します。

338

OAuth の用語モバイルアプリケーションでの認証、セキュリティ、ID

継続的な認証1. モバイルアプリケーションを開きます。2. セッション ID が有効な場合は、アプリケーションが直ちに起動します。セッション ID が期限切れの場合

は、初期認証から取得された更新トークンをアプリケーションで使用して、更新されたセッション ID を取得します。

3. アプリケーションが起動します。

PIN の認証 (省略可能)1. しばらく使用せずに時間を置いた後、モバイルアプリケーションを開きます。2. 経過時間が設定済みの PIN タイムアウト値を超えている場合は、パスコード入力画面が表示されます。PIN

を入力します。

メモ: PIN の保護は、モバイルポリシーの機能であり、Salesforce 接続アプリケーション定義で有効になっている場合にのみ使用されます。ユーザがオンラインかオフラインかに関わらず、アプリケーションを最後に使用してから一定時間が経過すると表示されます。「PIN セキュリティについて」を参照してください。

3. アプリケーションで既存のセッション ID が使用されます。4. アプリケーションが起動します。

OAuth 2.0 ユーザエージェントフローユーザエージェント認証フローは、ユーザのモバイルデバイスにあるクライアントアプリケーションで使用されます。認証は、ユーザエージェントの発生元が同じポリシーに基づいています。ユーザエージェントフローでは、クライアントアプリケーションは HTTP リダイレクトの形式でアクセストークンを受信します。クライアントアプリケーションは、ユーザエージェントにアクセスできる他の Web サーバまたはローカルリソースにユーザエージェントをリダイレクトするよう認証サーバに要求します。この要求により、レスポンスからアクセストークンを抽出し、アクセストークンがクライアントアプリケーションに渡されます。トークンレスポンスは、URL でハッシュ (#) フラグメントとして指定されます。これは、セキュリティ保護のためであり、そのサーバだけでなく、参照ヘッダーで指定されている他のサーバにトークンが渡されないようにします。このユーザエージェント認証フローでは、クライアントの秘密は使用しません。これは、クライアントの実行可能ファイルがエンドユーザのコンピュータ上またはデバイス上にあり、クライアントの秘密にアクセスできたり、探索したりすることができるためです。

警告: アクセストークンは符号化され、リダイレクト URI になっているため、エンドユーザや、コンピュータまたはデバイス上にある他のアプリケーションに公開できます。JavaScript を使用して認証する場合、window.location.replace(); をコールし、ブラウザの履歴からのコールバックを削除します。

339

OAuth 2.0 ユーザエージェントフローモバイルアプリケーションでの認証、セキュリティ、ID

1. クライアントアプリケーションでは、アプリケーションを認証および承認するために、ユーザを Salesforce

に移動します。2. ユーザは常に、この認証フローへのアクセスを承認する必要があります。アクセス承認後、アプリケーショ

ンは Salesforce からのコールバックを受信します。コンシューマがアクセストークンを入手したら、そのアクセストークンを使用して、エンドユーザの代わりにデータにアクセスし、更新トークンを取得できます。更新トークンを使用すると、アクセストークンが何らかの理由で無効になった場合に、コンシューマが新しいアクセストークンを取得できます。

OAuth 2.0 更新トークンフローコンシューマがアクセスを認証されたら、トークンを更新して新しいアクセストークン (セッション ID) を取得できます。これは、コンシューマが Web サーバまたはユーザエージェントフローのいずれかを使用して、更新トークンをすでに受信した場合のみに実行できます。アクセストークンを無効にするタイミングおよび新しいトークンを適用するタイミングを決定するのは、コンシューマです。べアラーフローは、コンシューマが更新トークンフローを受信した後でのみ使用できます。更新トークン認証フローの手順は、次のとおりです。各ステップの詳細は次のとおりです。1. コンシューマは既存の更新トークンを使用して、新しいアクセストークンを要求します。2. 要求の確認後、Salesforce からクライアントに応答が送信されます。

メモ: Mobile SDK アプリケーションでは、SmartStore 機能を使用してデータをオフラインで使用するためにローカルに保存できます。SmartStore データは、本質的に揮発性です。有効期限は、認証済みユーザおよび OAuth トークンの状態に関係しています。ユーザがアプリケーションからログアウトすると、そのユーザに関連付けられているスープデータは SmartStore によりすべて削除されます。同様に、OAuth 更新トークンが取り消されるか期限切れになると、ユーザのアプリケーション状態がリセットされ、SmartStore のすべてのデータが消去されます。アプリケーションの設計時には、SmartStore データの揮発性を十分に考

340

OAuth 2.0 更新トークンフローモバイルアプリケーションでの認証、セキュリティ、ID

慮してください。この警告は、組織で更新トークンに短期の有効期限を設定している場合に特に重要です。

範囲パラメータの値OAuth では、サーバおよびクライアントの両方に範囲設定が必要です。サーバ側とクライアント側間の同意によって、範囲に関する契約が定義されます。• サーバ側 — Salesforce サーバの接続アプリケーションで、範囲権限を定義します。この設定により、Mobile

SDKアプリケーションなど、クライアントアプリケーションが要求できる範囲が決まります。少なくとも、コードで指定した内容に合わせて接続アプリケーションの OAuth 設定を指定します。ハイブリッドアプリケーションおよび iOS ネイティブアプリケーションの場合、通常は refresh_token、web、api で十分です。Android ネイティブアプリケーションの場合、通常は refresh_token および api で十分です。

• クライアント側 — Mobile SDK アプリケーションで範囲要求を定義します。クライアントの範囲要求は、接続アプリケーションの範囲権限のサブセットである必要があります。

サーバ側の設定scopeパラメータによって、Salesforce組織でクライアントアプリケーションがアクセスできる項目を細かく設定できます。scope の有効値は次のとおりです。

説明値

REST API や Bulk API などの API を使用して、現在のログインユーザの取引先へのアクセスを許可します。この値には、Chatter REST APIリソースへのアクセスを許可する chatter_api も含まれます。

api

Chatter REST API リソースへのアクセスのみを許可します。chatter_api

接続アプリケーションに関連付けられている組織のカスタム権限へのアクセスを許可し、現在のユーザで各権限が有効かどうかを示します。

custom_permissions

ログインユーザがアクセスできるすべてのデータへのアクセスを許可し、その他すべての範囲が対象となります。full は更新トークンを返しません。更新トー

full

クンを取得するには、refresh_token の範囲を明示的に要求する必要があります。

ID URL サービスへのアクセスを許可します。profile、email、address、phone

を要求すれば、id を使用した場合と同じ結果を個別に得られます。これらの結果はすべて一致します。

id

OpenID Connect アプリケーションの現在のログインユーザの一意の識別子へのアクセスを許可します。アクセストークンの他にも、「OpenID Connect の仕様」に従って、OAuth 2.0 ユーザエージェントフローおよび OAuth 2.0 Web サーバ認証フローで openid 範囲を使用して、署名付き ID トークンを再度取得できます。

openid

341

範囲パラメータの値モバイルアプリケーションでの認証、セキュリティ、ID

説明値

更新トークンを受信できる場合に、それを返すように指定します。これにより、ユーザがオフラインのときにアプリケーションがユーザのデータを操作できます。これは、offline_access を要求した場合と同じ意味になります。

refresh_token

Visualforce ページへのアクセスを許可します。visualforce

Web で access_token を使用することを許可します。これには visualforce

も含まれ、Visualforce ページへのアクセスが許可されます。web

メモ: Mobile SDKアプリケーションでは、サーバ側の [接続アプリケーション] 設定で常に refresh_token

を選択する必要があります。範囲に fullを選択しても、refresh_tokenを明示的に選択する必要があります。

クライアント側の設定Mobile SDK アプリケーションの範囲の設定は、次のルールで制御されます。

Mobile SDK アプリケーションの設定範囲

アプリケーションの Mobile SDK から暗黙的に要求されます。要求に含める必要はありません。

refresh_token

Salesforce REST API コールを行う場合に、要求に含めます (ほとんどのアプリケーションに適用されます)。

api

Salesforce組織で定義されたページにアプリケーションからアクセスする場合に、要求に含めます (Salesforce

web

ベースの Web ページを読み込むハイブリッドアプリケーションおよびネイティブアプリケーションの場合)。

すべての権限を要求する場合に含めます (Mobile SDKでは、refresh_token が暗黙的に要求されます)。

full

アプリケーションから Chatter REST API をコールする場合に、要求に含めます。

chatter_api

(不要)id

代わりに、web を使用します。visualforce

ID URL の使用id 範囲パラメータでは、アクセストークンのほか、トークン応答の一部として ID URL も返されます。

342

ID URL の使用モバイルアプリケーションでの認証、セキュリティ、ID

ID URL は、ユーザを一意に識別する文字列であるだけでなく、ユーザの詳細情報について (有効なアクセストークンを使用して) クエリするために使用できる RESTful APIでもあります。Salesforceは、ユーザに関する基本的なパーソナライズ設定情報、ユーザの写真などのクライアントが通信する重要なエンドポイント、およびアクセス可能な API エンドポイントを返します。URL の形式は、https://login.salesforce.com/id/orgID/userID です。ここで、orgId はユーザが属する Salesforce 組織の ID で、userID は Salesforce のユーザ ID です。

メモ: Sandbox では、login.salesforce.com は test.salesforce.com に置き換えられます。URL は必ず https である必要があります。

ID URL パラメータ次のパラメータは、アクセストークンや ID URL と併用できます。アクセストークンは、認証要求ヘッダーやoauth_token パラメータのある要求で使用できます。

説明パラメータ

「アクセストークンの使用」を参照してください。アクセストークン

このパラメータは省略可能です。返される出力の形式を指定します。有効な値は、次のとおりです。

format

• json

• xml

formatパラメータを使用する代わりに、クライアントは次のいずれかを使用して、受け入れ要求ヘッダーの返される形式も指定できます。• Accept: application/json

• Accept: application/xml

• Accept: application/x-www-form-urlencoded

次の点に注意してください。• ワイルドカードを受け入れるヘッダーが許可されます。*/*が受け入れ

られ、JSON を返します。• 値のリストも受け入れられ、左から右に確認されます。たとえば、

application/xml,application/json,application/html,*/* はXML を返します。

• format パラメータは、受け入れ要求ヘッダーより優先されます。

このパラメータは省略可能です。SOAP APIバージョン番号またはリテラル文字列 latest を指定します。この値が指定されていない場合、返されるAPI

version

URL に、クライアントが文字列置換を実行するためのバージョン番号の代わりに、リテラル値 {version} が含まれます。値が latest として指定されると、最新の API バージョンが使用されます。

このパラメータは省略可能で、ヘッダー内でのみ使用できます。URL パラメータとしては使用できません。最適なフォーマットになるように出力を

PrettyPrint

343

ID URL の使用モバイルアプリケーションでの認証、セキュリティ、ID

説明パラメータ

指定します。たとえば、ヘッダーで X-PrettyPrint:1 を使用します。この値が指定されない場合、返される XML または JSON は読みやすさではなくサイズで最適化されます。

このパラメータは省略可能です。有効な JavaScript 関数名を指定します。このパラメータは、形式が JSON として指定されている場合にのみ使用されま

callback

す。出力はこの関数名 (JSONP) でラップされます。たとえば、https://server/id/orgid/userid/に対する要求では {"foo":"bar"}

を返し、https://server/id/orgid/userid/?callback=bazに対する要求では baz({"foo":"bar"}); を返します。

ID URL レスポンス有効な要求では、JSON 形式で次の情報が返されます。• id — ID URL (クエリされた URL と同じ)

• asserted_user — 指定されたアクセストークンがこの ID に発行されたかどうかを示す Boolean 値• user_id — Salesforce のユーザ ID

• username — Salesforce ユーザ名• organization_id — Salesforce 組織 ID

• nick_name — クエリ対象のユーザのコミュニティのニックネーム• display_name — クエリ対象のユーザの表示名 (氏名)

• email — クエリ対象のユーザのメールアドレス• email_verified — 組織でメールの確認が有効化されているか (true)、否か (false) を示します。• first_name — ユーザの名• last_name — ユーザの姓• timezone — ユーザの設定のタイムゾーン• photos — ユーザプロファイルの写真への URL の対応付け

メモ: これらの URL にアクセスするには、アクセストークンを渡す必要があります。「アクセストークンの使用」を参照してください。

– picture

– thumbnail

• addr_street — ユーザの設定の住所で指定されている町名・番地• addr_city — ユーザの設定の住所で指定されている市区郡• addr_state — ユーザの設定の住所で指定されている都道府県• addr_country — ユーザの設定の住所で指定されている国• addr_zip — ユーザの設定の住所で指定されている郵便番号• mobile_phone — ユーザの設定の携帯電話番号

344

ID URL の使用モバイルアプリケーションでの認証、セキュリティ、ID

• mobile_phone_verified — 有効な番号であることをユーザが確認した携帯電話番号。「モバイルユーザ」を参照してください。

• status — ユーザの現在の Chatter 状況– created_date: 2010-05-08T05:17:51.000Z など、ユーザの前回の投稿の作成日付の xsd datetime 値– body: 投稿の本文

• urls — 指定されたユーザで使用できる、さまざまな API エンドポイントを含む対応付け

メモ: REST エンドポイントへのアクセスでは、アクセストークンを渡す必要があります。「アクセストークンの使用」を参照してください。

– enterprise (SOAP)

– metadata (SOAP)

– partner (SOAP)

– rest (REST)

– sobjects (REST)

– search (REST)

– query (REST)

– recent (REST)

– profile

– feeds (Chatter)

– feed-items (Chatter)

– groups (Chatter)

– users (Chatter)

– custom_domain — 組織に設定または伝搬されたカスタムドメインがない場合、この値は省略されます。

• active — クエリ対象のユーザが有効であるかどうかを指定する Boolean 値• user_type — クエリ対象のユーザのタイプ• language — クエリ対象のユーザの言語• locale — クエリ対象のユーザのロケール• utcOffset — クエリ対象のユーザのタイムゾーンの UTC からのオフセット (ミリ秒単位)

• last_modified_date — 2010-06-28T20:54:09.000Z など、ユーザの前回の変更の xsd datetime 形式• is_app_installed — この値は、接続アプリケーションが現在のユーザの組織にインストールされてい

て、ユーザのアクセストークンが OAuth フローを使用して作成されている場合に true になります。接続アプリケーションがインストールされていない場合、このプロパティは (false になるのではなく) 存在しません。応答を解析する場合、このプロパティの有無と値の両方を確認してください。

• mobile_policy — モバイル接続アプリケーションを管理する値を指定します。これらの値は、接続アプリケーションが現在のユーザの組織にインストールされていて、アプリケーションでセッションタイムアウト値と PIN (個人識別番号) の長さの値が定義されている場合にのみ使用できます。– screen_lock — 非活動状態になってから画面をロックするまでの待機時間– pin_length — モバイルアプリケーションにアクセスするために必要な識別番号の長さ

345

ID URL の使用モバイルアプリケーションでの認証、セキュリティ、ID

• push_service_type — この応答値は、接続アプリケーションが Apple Push Notification Service (APNS) for iOS 転送通知に登録されている場合は appleに設定され、Google Cloud Messaging (GCM) for Android 転送通知に登録されている場合は androidGcm に設定されます。応答値は配列型です。

• custom_permissions — custom_permissions範囲パラメータが要求にある場合、接続アプリケーションに関連付けられた組織のカスタム権限を含む対応付けが応答にあります。接続アプリケーションが組織にインストールされていない場合や、カスタム権限に関連付けられていない場合、custom_permissions

の対応付けは応答にありません。次に、要求の例を示します。http://login.salesforce.com/services/oauth2/authorize?response_type=token&client_id=3MVG9lKcPoNINVBKV6EgVJiF.snSDwh6_2wSS7BrOhHGEJkC_&redirect_uri=http://www.example.org/qa/security/oauth/useragent_flow_callback.jsp&scope=api%20id%20custom_permissions

次に、ID URL レスポンスの JSON ブロックを示します。"custom_permissions":{"Email.View":true,"Email.Create":false,"Email.Delete":false

}

XML 形式のレスポンスは、次のとおりです。<?xml version="1.0" encoding="UTF-8"?><user xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><id>https://yourInstance.salesforce.com/id/00Dx0000001T0zk/005x0000001S2b9</id><asserted_user>true</asserted_user><user_id>005x0000001S2b9</user_id><organization_id>00Dx0000001T0zk</organization_id><nick_name>admin1.2777578168398293E12foofoofoofoo</nick_name><display_name>Alan Van</display_name><email>[email protected]</email><status>

<created_date xsi:nil="true"/><body xsi:nil="true"/>

</status><photos>

<picture>https://yourInstance.salesforce.com/profilephoto/005/F</picture><thumbnail>https://yourInstance.salesforce.com/profilephoto/005/T</thumbnail>

</photos><urls>

<enterprise>https://yourInstance.salesforce.com/services/Soap/c/{version}/00Dx0000001T0zk

</enterprise><metadata>https://yourInstance.salesforce.com/services/Soap/m/{version}/00Dx0000001T0zk

</metadata><partner>https://yourInstance.salesforce.com/services/Soap/u/{version}/00Dx0000001T0zk

</partner><rest>https://yourInstance.salesforce.com/services/data/v{version}/</rest><sobjects>https://yourInstance.salesforce.com/services/data/v{version}/sobjects/

346

ID URL の使用モバイルアプリケーションでの認証、セキュリティ、ID

</sobjects><search>https://yourInstance.salesforce.com/services/data/v{version}/search/</search><query>https://yourInstance.salesforce.com/services/data/v{version}/query/</query><profile>https://yourInstance.salesforce.com/005x0000001S2b9</profile>

</urls><active>true</active><user_type>STANDARD</user_type><language>en_US</language><locale>en_US</locale><utcOffset>-28800000</utcOffset><last_modified_date>2010-06-28T20:54:09.000Z</last_modified_date></user>

JSON 形式のレスポンスは、次のとおりです。{"id":"https://yourInstance.salesforce.com/id/00Dx0000001T0zk/005x0000001S2b9","asserted_user":true,"user_id":"005x0000001S2b9","organization_id":"00Dx0000001T0zk","nick_name":"admin1.2777578168398293E12foofoofoofoo","display_name":"Alan Van","email":"[email protected]","status":{"created_date":null,"body":null},"photos":{"picture":"https://yourInstance.salesforce.com/profilephoto/005/F",

"thumbnail":"https://yourInstance.salesforce.com/profilephoto/005/T"},"urls":

{"enterprise":"https://yourInstance.salesforce.com/services/Soap/c/{version}/00Dx0000001T0zk",

"metadata":"https://yourInstance.salesforce.com/services/Soap/m/{version}/00Dx0000001T0zk",

"partner":"https://yourInstance.salesforce.com/services/Soap/u/{version}/00Dx0000001T0zk",

"rest":"https://yourInstance.salesforce.com/services/data/v{version}/","sobjects":"https://yourInstance.salesforce.com/services/data/v{version}/sobjects/","search":"https://yourInstance.salesforce.com/services/data/v{version}/search/","query":"https://yourInstance.salesforce.com/services/data/v{version}/query/","profile":"https://yourInstance.salesforce.com/005x0000001S2b9"},

"active":true,"user_type":"STANDARD","language":"en_US","locale":"en_US","utcOffset":-28800000,"last_modified_date":"2010-06-28T20:54:09.000+0000"}

無効な要求を作成した後は、Salesforce から次のレスポンスを受信する可能性があります。

347

ID URL の使用モバイルアプリケーションでの認証、セキュリティ、ID

要求の問題エラーコード

HTTP403 (forbidden) — HTTPS_Required

アクセストークンがない403 (forbidden) — Missing_OAuth_Token

アクセストークンが無効403 (forbidden) — Bad_OAuth_Token

異なる組織のユーザ403 (forbidden) — Wrong_Org

ユーザ ID または組織 ID が無効または間違っている

404 (not found) — Bad_Id

無効になったユーザまたは無効な組織404 (not found) — Inactive

ユーザに組織または情報への適切なアクセス権がない

404 (not found) — No_Access

サイトの無効なエンドポイントへの要求404 (not found) — No_Site_Endpoint

サーバから応答がない404 (not found) — Internal Error

無効なバージョン406 (not acceptable) — Invalid_Version

無効なコールバック406 (not acceptable) — Invalid_Callback

Android アプリケーションでのカスタムログインサーバの設定Trialforce を使用する Salesforce パートナーなど、特殊な場合は、ユーザのログイン要求をカスタムログイン URI

にリダイレクトできます。Android では、ログインホストはサーバ接続と呼ばれます。SalesforceSDK プロジェクトのres/xml/servers.xml ファイルでサーバ接続の標準リストを参照できます。Mobile SDK では、このファイルを使用して本番サーバと Sandbox サーバを定義します。Android の場合、次のいずれかの方法を使用してデフォルトのログインホストを設定できる可能性があります。1. MDM の適用

• 起動時に、アプリケーションの MDM プロバイダによってログイン URI が設定されます。• MDM ポリシーでは、ユーザがログインホストを変更できないようにナビゲーションバーと設定アイコン

を非表示にすることもできます。

2. servers.xml ファイルを使用したアプリケーションによる設定ネイティブ Android プロジェクトで独自の res/xml/servers.xml ファイルを作成することで、カスタムサーバをランタイムリストに追加できます。servers.xmlファイルの最初にリストされているサーバがデフォルトのログインサーバとしてアプリケーションの起動時に使用されます。servers.xmlのルート XML

要素は <servers> です。このルートには、<server> エントリをいくつでも含めることができます。各<server>エントリには、name (わかりやすい任意の表示ラベル) と url (「https://」プレフィックスが含まれるログインサーバの Web アドレス) という 2 つの属性が必要です。

348

Android アプリケーションでのカスタムログインサーバの設定

モバイルアプリケーションでの認証、セキュリティ、ID

servers.xml ファイルの例を次に示します。<?xml version="1.0" encoding="utf-8"?><servers><server name="XYZ.com Login" url="https://myloginserver.cloudforce.com"/>

</servers>

メモ: Android エミュレータで XML の変更をテストするには、次の手順を実行することをお勧めします。a. エミュレータでアプリケーションが実行中の場合は強制終了します。b. エミュレータでアプリケーションをアンインストールします。c. フルクリーンアップと再構築を行います。d. アプリケーションを実行します。

3. [接続を追加] ボタンを使用したユーザによる設定ユーザは次の手順でカスタムログインサーバを設定できます。a. ログインしないでアプリケーションを開始します。b. ログイン画面で、左上隅にある設定アイコンをタップします。c. [サーバを変更] をタップします。d. [接続を追加] をタップします。e. 今後アクセスしたときにこの設定を識別できるように、名前を入力します。f. カスタムログインホストの URI を入力します。https://プレフィックスを必ず含めてください。次に、

一般的なコミュニティ URI の入力方法の例を示します。https://mycommunity-developer-edition.na15.force.com/fineapps

Mobile SDK ではデフォルトでこの機能が有効になっています。Mobile SDK for Android では、[サーバを変更] または [接続を追加] オプションをプログラムで無効にすることはできません。

重要:

• Android では、ログイン URL を指定するときに「https://」が常に含まれます。• 起動時に、コンパイル時の設定が MDM ランタイム設定で上書きされます。

iOS アプリケーションでのカスタムログインサーバの設定Trialforce を使用する Salesforce パートナーなど、特殊な場合は、ユーザのログイン要求をカスタムログイン URI

にリダイレクトできます。iOS アプリケーションでは、ログインサーバは多くの場合「ログインホスト」と呼ばれます。Mobile SDKによって、SalesforceSDKCore 製品で本番サーバと Sandbox サーバの標準ログイン URI が定義されます。これらの2 つのログインホストは、[接続を選択] ログイン画面に表示されます。iOS の場合、次のいずれかの方法を使用してデフォルトのログインホストを設定できる可能性があります。1. MDM の適用

349

iOS アプリケーションでのカスタムログインサーバの設定

モバイルアプリケーションでの認証、セキュリティ、ID

起動時に、アプリケーションの MDM プロバイダによってログイン URI が設定されます。•

• MDM ポリシーでは、ユーザがログインホストを変更できないようにナビゲーションバーと設定アイコンを非表示にすることもできます。

2. info.plist ファイルを使用したアプリケーションによる設定• アプリケーションは、プロジェクトの info.plistプロパティファイルでデフォルトのログイン URI を

設定できます。ログインホストプロパティ名は SFDCOAuthLoginHost です。• 起動時に、ユーザ定義のログインホストが SFDCOAuthLoginHost 設定で上書きされます。• デフォルトでは、SFDCOAuthLoginHost プロパティは「login.salesforce.com」に設定されています。• ログイン URI を指定するときに、「https://」などのプロトコルプレフィックスは使用しないでください。

3. [接続を追加] 画面を使用したユーザによる設定ユーザは次の手順でカスタムログインサーバを設定できます。a. ログインしないでアプリケーションを開始します。b. ログイン画面で [設定] をタップするか、上部のナビゲーションバーの「ギア」アイコン をタップし

ます。c. [接続を選択] 画面で、プラスアイコン をタップします。d. (省略可能ですが推奨) 今後アクセスしたときにこの設定を簡単に識別できるように、表示ラベルを入力

します。e. カスタムログインホストの URI を入力します。必ず https:// プレフィックスを削除してください。次

に、一般的なコミュニティ URI の入力方法の例を示します。mycommunity-developer-edition.na15.force.com/fineapps

Mobile SDKではデフォルトでこの機能が有効になっています。[接続を追加] オプションを無効にする場合は、SFLoginHostViewController プロパティを設定します。

重要:

• 起動時に、コンパイル時の設定が MDM ランタイム設定で上書きされます。• バージョン 4.1 より前の Mobile SDK for iOS アプリケーションでは、アプリケーションの設定バンドルで

カスタムログイン URI を定義していました。Mobile SDK 4.1 以降では、iOS アプリケーションの設定バンドルがなくなりました。代わりに、アプリケーションのinfo.plistファイルのSFDCOAuthLoginHost

プロパティを使用して、カスタムログイン URI を組み込むことができます。

関連トピック:

iOS アプリケーションでの設定アイコンの非表示

350

iOS アプリケーションでのカスタムログインサーバの設定

モバイルアプリケーションでの認証、セキュリティ、ID

iOS アプリケーションでの設定アイコンの非表示現在、iOS の Mobile SDK ログイン画面には、設定アイコンを含む上部ナビゲーションバーが表示されます。ユーザは設定アイコンを使用して、組み込みリストからログインサーバを選択したり、カスタムログイン URI を指定したりできます。ただし、会社によってはユーザにログインサーバの選択を許可しない場合があります。この制限が適用される場合、次のコードを使用して設定アイコンを非表示にできます。デフォルトでは、Salesforce Mobile SDK ログイン画面には上部ナビゲーションバーとその埋め込み設定アイコンの両方が表示されます。設定アイコンは、その歯車のような形状 から多くの場合「ギア」アイコンと呼ばれます。ログインサーバの切り替えを無効にするには、設定アイコン自体を非表示にするか、アイコンが含まれるナビゲーションを非表示にします。次の SFLoginViewController プロパティを使用して、これらの UI

要素の表示を制御します。

showSettingsIcon設定アイコンのみの表示を制御します。ナビゲーションバーの表示には影響しません。動作

意味値

デフォルト値。設定アイコンは表示され、アクセス可能です。

YES (デフォルト)

設定アイコンは表示されません。ユーザはログインホストリストにアクセスできず、カスタムホストを追加することもできません。

NO

例AppDelegate クラスの application:didFinishLaunchingWithOptions: メソッドに次の行を追加します。SFLoginViewController *loginViewController =

[SFLoginViewController sharedInstance];

loginViewController.showSettingsIcon = NO;

showNavbarナビゲーションバーの表示を制御します。これにより、設定アイコンの表示も制御されます。動作

意味値

デフォルト値。ナビゲーションバーは表示されます。設定アイコンは、showSettingsIcon プロパティに応じて表示されます。

YES (デフォルト)

351

iOS アプリケーションでの設定アイコンの非表示モバイルアプリケーションでの認証、セキュリティ、ID

意味値

ナビゲーションバーと設定アイコンは表示されません。ユーザはログインホストリストにアクセスできず、カスタムホストを追加することもできません。

NO

例AppDelegate クラスの application:didFinishLaunchingWithOptions: メソッドに次の行を追加します。SFLoginViewController *loginViewController =

[SFLoginViewController sharedInstance];

loginViewController.showNavbar = NO;

関連トピック:

iOS アプリケーションでのカスタムログインサーバの設定

OAuth トークンの取り消しユーザがアプリケーションからログアウトした、アプリケーションがタイムアウトした、または他の理由により無効になった場合、ログインしたユーザのログイン情報はモバイルアプリケーションからクリアされます。これにより、サーバ接続が効果的に終了します。また、Mobile SDK では、ログアウトの一環としてサーバから更新トークンも取り消されます。

トークンの取り消しOAuth 2.0 トークンを取り消すには、取り消しのエンドポイントを使用します。https://login.salesforce.com/services/oauth2/revoke

HTTP 要求の entity-body に application/x-www-form-urlencoded 形式を使用して、次のパラメータを含むPOST 要求を記述します。次に例を示します。

POST /revoke HTTP/1.1Host: https://login.salesforce.com/services/oauth2/revokeContent-Type: application/x-www-form-urlencoded

token=currenttoken

アクセストークンが含まれる場合、それを無効化してトークンを取り消します。要求トークンが含まれる場合、それを取り消して、すべての関連するアクセストークンを取り消します。認証サーバは、HTTP ステータスコード 200 を返し、要求が正常に処理されたことを示します。すべてのエラー条件については、ステータスコード 400 と次のいずれかのエラーレスポンスが使用されます。• unsupported_token_type — サポートされていないトークンのタイプ• invalid_token — トークンが無効

352

OAuth トークンの取り消しモバイルアプリケーションでの認証、セキュリティ、ID

Sandbox には、login.salesforce.com ではなく test.salesforce.com を使用してください。

Android ネイティブアプリケーションでの更新トークンの取り消し更新トークンが管理者によって取り消されると、デフォルトの動作では現在のユーザが自動的にログアウトされます。その結果、次のようになります。• アプリケーションで行う後続の REST API コールがすべて失敗する。• ユーザのアカウント情報と、キャッシュされたオフラインデータが破棄される。• ユーザがページから強制的に移動される。• アプリケーションを引き続き使用するには、ユーザが Salesforce に再度ログインする必要がある。これらの副次的影響として、管理者のアクションに対して安全な応答が行われます。

トークンの取り消しイベントトークンの取り消しイベントが発生すると、ClientManagerオブジェクトから Android スタイルの通知が送信されます。この通知が意図するアクションは、ClientManager.ACCESS_TOKEN_REVOKE_INTENT 定数で宣言されます。ACCESS_TOKEN_REVOKE_INTENT イベントリスナーは、SalesforceActivity.java、SalesforceListActivity.java、SalesforceExpandableListActivity.java、およびSalesforceDroidGapActivity.javaで実装されます。更新トークンが取り消されると、これらのリスナーによりユーザがログインページに自動的にログアウトされます。このことは、トーストメッセージによりユーザに通知されます。

接続アプリケーション

接続アプリケーションは、API を使用してアプリケーションを Salesforce と統合します。接続アプリケーションでは、標準の SAML および OAuth プロトコルを使用して、認証、シングルサインオンの提供、Salesforce API で使用するトークンの提供を行います。接続アプリケーションでは、標準の OAuth 機能に加え、システム管理者がさまざまなセキュリティポリシーを設定したり、対応するアプリケーションを使用できるユーザを明示的に制御したりできます。開発者またはシステム管理者は、次の情報を指定して Salesforce の接続アプリケーションを定義します。• 名前、説明、ロゴ、連絡先情報• Salesforce がアプリケーションを見つけて認証または識別できるようにするための URL

• 認証プロトコル: OAuth、SAML、またはその両方• 接続アプリケーションが実行されている可能性のある省略可能な IP 範囲• 接続アプリケーションが適用できるモバイルポリシーに関する省略可能な情報Salesforce Mobile SDKアプリケーションは、接続アプリケーションを使用して Salesforce OAuth サービスにアクセスし、Salesforce REST API をコールします。

353

Android ネイティブアプリケーションでの更新トークンの取り消し

モバイルアプリケーションでの認証、セキュリティ、ID

PIN セキュリティについてSalesforce 接続アプリケーションには、アプリケーションでの PIN 保護を介した追加のセキュリティレイヤがあります。この PIN 保護はモバイルアプリケーション自体のものであり、デバイスの PIN 保護や Salesforce 組織が提供するログインセキュリティとは異なります。PIN 保護を使用するためには、開発者が接続アプリケーションの作成時に[画面ロックと PIN 保護を実装]チェックボックスをオンにする必要があります。オンにすることで、モバイルアプリケーション管理者が、PIN 保護の強制実行、タイムアウト期間のカスタマイズ、PIN の長さの設定を行うかどうかを選択できます。

メモ: PIN セキュリティはモバイルデバイスのオペレーティングシステムで実装されるため、ネイティブおよびハイブリッドのモバイルアプリケーションのみが PIN 保護を使用でき、HTML5 Web アプリケーションは PIN 保護を使用できません。

実際には、PIN 保護を使用して、モバイルアプリケーションが指定した時間 (分単位) 使用されていない場合に動作を停止させることができます。モバイルアプリケーションがバックグラウンドに渡されても、経過時間は引き続き記録されます。PIN 保護のしくみは、次のとおりです。1. 電話を有効にし、デバイスの PIN を入力します。2. Mobile SDK アプリケーションを起動します。3. Salesforce 組織のログイン情報を入力します。4. Mobile SDK アプリケーションの PIN コードを入力します。5. アプリケーションで操作を行い、別のアプリケーションを開く (コールの受信など) ことによってアプリケー

ションをバックグラウンドに送ります。6. アプリケーションがタイムアウトになります。7. アプリケーションを再び開き、アプリケーションの PIN 画面 (デバイス用ではなく、Mobile SDK アプリケー

ション用) が表示されます。8. アプリケーションの PIN を入力し、操作を再開できます。

OAuth 2.0 サイトおよび Force.com サイトを使用したポータル認証

Salesforce Spring '13 リリースでは、ポータル認証の柔軟性が強化されました。アプリケーションが Salesforceポータルで実行されている場合、Force.com サイトで OAuth 2.0 を使用して、ポータルユーザの代わりに API アクセストークンを取得できます。この設定では、次の操作を実行できます。• SOAP API login() コールではなく、認証プロバイダおよび SAML を使用してポータルユーザを認証する。• アプリケーション内でのユーザのログイン情報の処理を回避する。• Force.com サイトで提供されるログイン画面をカスタマイズする。開始方法は次のとおりです。1. Force.com サイトをポータルに関連付けます。サイトで、ポータルに一意の URL が生成されます。「ポータ

ルと Force.com サイトの関連付け」を参照してください。

354

PIN セキュリティについてモバイルアプリケーションでの認証、セキュリティ、ID

2. Force.comサイトで、カスタムログインページを作成します。「Force.com Site のログインおよび登録設定の管理」を参照してください。

3. サイトで生成された一意の URL を、ユーザのログイン要求のリダイレクトドメインとして使用します。OAuth 2.0 サービスでカスタムホスト名が認識され、ユーザがまだ認証されていない場合はサイトのログインページにリダイレクトされます。

例: たとえば、次のように https://login.salesforce.com にはリダイレクトしません。https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=<your_client_id>&redirect_uri=<your_redirect_uri>

次のように、https://mysite.secure.force.com などの一意の Force.com サイト URL にリダイレクトします。https://mysite.secure.force.com/services/oauth2/authorize?response_type=code&client_id=<your_client_id>&redirect_uri=<your_redirect_uri>

詳細およびデモビデオについては、Force.com Developer Relations Blogs ページの「OAuth for Portal Users」を参照してください。

Salesforce Mobile SDK アプリケーションでの MDM の使用

モバイルデバイス管理 (MDM) では、アプリケーションの設定、更新、および認証を容易に行うことができます。Salesforce および Mobile SDK では、接続アプリケーションに MDM を使用できます。MDM を使用するには、Salesforce システム管理者および MDM プロバイダと協力します。Salesforce システム管理者は、使用事例に合わせて接続アプリケーションを設定します。MDM プロバイダは、モバイルアプリケーション設定を顧客のデバイスに配布する、信頼できるサードパーティです。たとえば、MDM を使用して、アプリケーションのカスタムログイン URL を設定できます。また、MDM を使用して、証明書ベースの認証を行うこともできます。この場合、証明書を MDM プロバイダにアップロードします。MDM を有効にするために、Mobile SDK アプリケーションコードを変更する必要はありません。次に、基本的な MDM ランタイムフローの概要を示します。

認証および設定のランタイムフロー1. 顧客が MDM 対応Mobile SDKアプリケーションをダウンロードするには、まず MDM プロバイダのアプリケー

ションをインストールします。2. MDM プロバイダは、そのアプリケーションを使用して、次の項目をデバイスに転送します。

• Mobile SDK アプリケーション• 指定した設定の詳細 (カスタムログイン URL や高度なセキュリティ設定など)

• ユーザ証明書 (認証にも MDM を使用している場合)

3. 顧客がアプリケーションを起動したときの動作は、モバイルオペレーティングシステムによって異なります。

355

Salesforce Mobile SDK アプリケーションでの MDM の使用

モバイルアプリケーションでの認証、セキュリティ、ID

Android: 証明書ベースの認証をサポートしている場合、ログインサーバが証明書を要求します。Android

は、Web ビューを起動して、顧客が選択できる 1 つ以上の証明書のリストを提供します。•

• iOS: Mobile SDKアプリケーションは、Salesforce接続アプリケーション定義で証明書ベースの認証が有効になっているかどうかをチェックします。有効になっている場合、アプリケーションは Safari ウィンドウに移動します。Safari は、保存されている MDM 証明書を取得し、透過的にデバイスを認証します。

4. 証明書を受け入れたら、ログインサーバがアクセストークンおよび更新トークンをアプリケーションに送信します。

5. Salesforce は、顧客のデータへのアクセスを要求する標準画面を表示します。次のセクションでは、Mobile SDK でサポートされる MDM 設定オプションについて説明します。

証明書ベースの認証証明書を使用した認証により、ユーザ名とパスワードを排除して、モバイルユーザのプロビジョニングと日常のモバイル管理業務を簡略化します。Salesforce では、ユーザ認証をさらに効率的に行うために X.509 証明書を使用するか、ログインプロセスの 2 つ目の要素として使用します。証明書ベースの認証の MDM 設定

モバイルユーザの証明書ベースの認証を有効にするには、MDM スイートを介してキー - 値ペアの割り当てを設定する必要があります。サポートされているキーは、次のとおりです。

説明プラットフォーム型キー

true の場合、証明書ベースの認証フローが開始されます。Android: Web ビュー内の認証でデバイスのユーザ証明書を使用します。

Android、iOSBooleanRequireCertAuth

iOS: すべての認証要求でユーザを Safari にリダイレクトします。

ユーザ認証のアプリケーションで選択されたデバ

AndroidStringManagedAppCertAlias

イスにリリースされる証明書の別名。Android の場合にのみ必要になります。

メモ: 証明書ベースの認証を使用するためのデバイスの OS の最小バージョン要件があります。Android

の場合、サポートされる最小バージョンは 5.0 です。iOS の場合、サポートされる最小バージョンは 7.0

です。

356

Salesforce Mobile SDK アプリケーションでの MDM の使用

モバイルアプリケーションでの認証、セキュリティ、ID

キー - 値ペアの割り当てを保存すると、更新された証明書ベースの認証フローを使用するモバイルアプリケーションを MDM スイートを介してユーザに転送できます。

自動カスタムホストプロビジョニングカスタムログインホストの設定をモバイルユーザに転送できるようになりました。これにより、モバイルユーザは、ストレスやミスの原因となりやすいログインホストの長い URL を手動で入力する必要がなくなります。モバイルユーザに複数のカスタムログインホストを定義するように、MDM を介してキー - 値ペアの割り当てを設定できます。自動カスタムホストプロビジョニングの MDM 設定

カスタムログインホスト設定をモバイルユーザに転送するには、MDM スイートを介してキー - 値ペアの割り当てを設定する必要があります。サポートされているキーは、次のとおりです。

説明プラットフォームデータ型キー

ログインホスト。配列の最初の値がデフォルトのホストです。Android: ホストの URL にhttps:// が必要です。

Android、iOSString、String ArrayAppServiceHosts

iOS:ホストの URL に https://

は必要ありません。

ホストの表示ラベル。AppServiceHostLabels

エントリの数は、

Android、iOSString、String ArrayAppServiceHostLabels

AppServiceHosts エントリの数と一致している必要があります。

true の場合、ユーザはSalesforce1から接続できる

Android、iOSBooleanOnlyShowAuthorizedHosts

ホストのリストを変更できません。

その他のセキュリティの機能強化モバイルアプリケーションがバックグラウンドで実行されているときは常にクリップボードのコンテンツをクリアすることで、iOS ユーザのセキュリティ層をさらに追加できます。ユーザは、日々の業務の一環として機密データをコピーして貼り付けることがありますが、この機能強化により、バックグラウンドでアプリケーションが実行されているときは常にクリップボードにコピーするデータが確実にクリアされます。

357

Salesforce Mobile SDK アプリケーションでの MDM の使用

モバイルアプリケーションでの認証、セキュリティ、ID

その他のセキュリティの機能強化の MDM 設定モバイルアプリケーションがバックグラウンドで実行されているときに iOS ユーザのクリップボードをクリアするには、MDM スイートを介してキー - 値ペアの割り当てを設定する必要があります。サポートされているキーは、次のとおりです。

説明プラットフォームデータ型キー

true の場合、モバイルアプリケーションがバック

iOSBooleanClearClipboardOnBackground

グラウンドで実行されているときに iOS クリップボードのコンテンツがクリアされます。これにより、ユーザが誤ってアプリケーションの外部に機密データをコピーして貼り付けてしまうことを回避できます。

メモ: モバイルアプリケーションの動作が予期せず停止すると、コピーされたデータがクリップボードに残る可能性があります。ユーザがモバイルアプリケーションを開始して、そのモバイルアプリケーションがバックグラウンドで実行されると、クリップボードのコンテンツがクリアされます。

このセキュリティ機能は、OS 5.0 以降が実行されていて、Android for Work が設定されている Android デバイスの Android で使用できます。MDM プロバイダに連絡して、Android ユーザにこの機能を設定してください。

358

Salesforce Mobile SDK アプリケーションでの MDM の使用

モバイルアプリケーションでの認証、セキュリティ、ID

第 14 章 Mobile SDK アプリケーションでのCommunities の使用

Salesforce Communities は、以前のリリースのポータル機能に置き換わるソーシャルアグリゲーション機能です。コミュニティには、Salesforce の制限で許可されている百

トピック:

• コミュニティとMobile SDK アプリケーション

万人までのユーザを含めることができます。適切に設定すれば、顧客は、コミュニティログイン情報を使用して、Mobile SDK アプリケーションにアクセスできます。Communities では、Site.comを利用して、コミュニティサイトやログイン画面をブランド設定することもできます。• 「API の有効化」プ

ロファイルを設定する Salesforceコミュニティの機能についての詳細は、Salesforceヘルプの「Salesforce コミュ

ニティの概要」を参照してください。• 権限セットを設定する

• API アクセス権をユーザに付与する

• ログインエンドポイントを設定する

• コミュニティのブランド設定

• コミュニティのログイン、ログアウト、およびセルフ登録ページのカスタマイズ

• コミュニティでの外部認証の使用

• 例: Mobile SDK アプリケーションからアクセスできるようにコミュニティを設定する

• 例: Facebook 認証できるようにコミュニティを設定する

359

コミュニティと Mobile SDK アプリケーション

コミュニティメンバーが Mobile SDK アプリケーションにログインできるようにするには、Salesforce で適切に権限を設定し、コミュニティ URL を認識するようにアプリケーションのログインサーバ設定を変更します。コミュニティでは、指定のメンバーが Mobile SDK アプリケーションを使用して Salesforce にアクセスできます。独自のコミュニティログインエンドポイントを定義し、コミュニティ機能を使用して、仕様に従ってブランド化されたコミュニティログインページを作成します。また、一般的なプロバイダのリストから認証プロバイダおよび SAML ID プロバイダを選択することもできます。コミュニティのメンバーシップは、プロファイルと権限セットで決まります。コミュニティメンバーがMobile

SDK アプリケーションを使用できるようにするには、次のように設定します。• 各コミュニティメンバーに「API の有効化」権限があることを確認します。この権限は、プロファイルまた

は権限セットを使用して設定できます。• 「API の有効化」プロファイルまたは権限セットを含めるようにコミュニティを設定します。• コミュニティのログインエンドポイントを使用するように Mobile SDK アプリケーションを設定します。これらの手順の概要の他に、必要な手順を実行してユーザを適切に設定する必要があります。「例: Mobile SDK

アプリケーションからアクセスできるようにコミュニティを設定する」では、Mobile SDK アプリケーションのコミュニティ設定プロセスについて説明します。コミュニティ機能についての詳細は、『Salesforce Communites

実装ガイド』を参照してください。

メモ: コミュニティログインは、Android や iOS のネイティブおよびハイブリッドローカル Mobile SDK でサポートされています。現在、Visualforce を使用するハイブリッドリモートアプリケーションではサポートされていません。

「API の有効化」プロファイルを設定する

コミュニティを初めて使用する場合は、まず組織のコミュニティ機能を有効にします。「Salesforce Communities

の有効化」を参照してください。ドメイン名を作成するように求められた場合、ドメイン名に SSL (https://)

を使用しないでください。コミュニティを設定する場合は、「コミュニティの作成」を参照してください。コミュニティ機能を有効にしたときに作成したドメイン名に基づいて、コミュニティ URL を定義します。次に、「API の有効化」権限のあるプロファイルを 1 つ以上設定します。これらのプロファイルを使用して、コミュニティメンバーの Mobile SDK アプリケーションを有効にできます。詳細は、「例: Mobile SDK アプリケーションからアクセスできるようにコミュニティを設定する」のチュートリアルを参照してください。1. 新しいプロファイルを作成するか、既存のプロファイルを編集します。2. プロファイルを詳細を編集して、[システム管理者権限] の [API の有効化] を選択します。3. 変更を保存して、[設定] から、[クイック検索] ボックスに「コミュニティ」と入力し、[すべてのコミュニ

ティ] を選択して、コミュニティを編集します。4. コミュニティの名前を選択します。その後、[管理] > [メンバー] をクリックします。5. 「API の有効化」プロファイルを [選択済みプロファイル] に追加します。

360

コミュニティと Mobile SDK アプリケーションMobile SDK アプリケーションでの Communities の使用

これで、これらのプロファイルが割り当てられているユーザに API アクセス権が付与されました。プロファイルの概要は、Salesforce ヘルプの「プロファイル」を参照してください。

権限セットを設定する

権限セットを使用して、コミュニティのモバイルアプリケーションを有効にすることもできます。1. 「API の有効化」権限を既存の権限セットに追加するには、[設定] から、[クイック検索] ボックスに「権限

セット」と入力し、[権限セット] を選択して権限セットを選択し、ステップ 6 に進みます。2. 権限セットを作成するには、[設定] から、[クイック検索]ボックスに「権限セット」と入力し、[権限セット]

を選択します。3. [新規] をクリックします。4. 権限セットに表示ラベルを指定して、Enter キーを押すと、自動的に API 名が作成されます。5. [次へ] をクリックします。6. [アプリケーション] セクションで、[アプリケーション権限] をクリックします。

7. [アプリケーション権限] をクリックして [システム] > [システム権限] を選択します。

361

権限セットを設定するMobile SDK アプリケーションでの Communities の使用

8. [システム権限] ページで [編集] をクリックして [API の有効化] を選択します。9. [保存] をクリックします。10. [設定] から、[クイック検索] ボックスに「コミュニティ」と入力し、[すべてのコミュニティ]を選択して、

コミュニティ名の横にある [管理] をクリックします。11. [管理] で、[メンバー] をクリックします。12. [権限セットを選択] で、「API の有効化」権限セットを [選択済みの権限セット] に追加します。これで、この権限セットのユーザに API アクセス権が付与されました。

API アクセス権をユーザに付与する

API アクセス権をコミュニティユーザに拡張するには、「API の有効化」権限を設定するプロファイルまたは権限セットにコミュニティユーザを追加します。この権限を含むプロファイルまたは権限セットをまだ設定していない場合は、「「API の有効化」プロファイルを設定する」および「権限セットを設定する」を参照してください。

ログインエンドポイントを設定する

最後に、コミュニティログインエンドポイントを使用するようにアプリケーションを設定します。アプリケーションのモバイルプラットフォームにより、この設定方法が決まります。

AndroidAndroid では、ログインホストはサーバ接続と呼ばれます。SalesforceSDK プロジェクトのres/xml/servers.xml ファイルでサーバ接続の標準リストを参照できます。Mobile SDK では、このファイルを使用して本番サーバと Sandbox サーバを定義します。ネイティブ Android プロジェクトで独自のres/xml/servers.xml ファイルを作成することで、カスタムサーバをランタイムリストに追加できます。servers.xmlファイルの最初にリストされているサーバがデフォルトのログインサーバとしてアプリケーションの起動時に使用されます。servers.xmlのルート XML 要素は <servers>です。このルートには、<server>

エントリをいくつでも含めることができます。各 <server>エントリには、name (わかりやすい任意の表示ラ

362

API アクセス権をユーザに付与するMobile SDK アプリケーションでの Communities の使用

ベル) と url (「https://」プレフィックスが含まれるログインサーバの Web アドレス) という 2 つの属性が必要です。次に例を示します。<?xml version="1.0" encoding="utf-8"?><servers><server name="XYZ.com Login" url="https://myloginserver.cloudforce.com"/>

</servers>

iOSバージョン 4.1 より前の Mobile SDK for iOS アプリケーションでは、アプリケーションの設定バンドルでカスタムログイン URI を定義していました。Mobile SDK 4.1 以降では、iOS アプリケーションの設定バンドルがなくなりました。代わりに、アプリケーションの info.plist ファイルの SFDCOAuthLoginHost プロパティを使用して、カスタムログイン URI を組み込むことができます。顧客は、アプリケーションのランタイムで独自のカスタムログインホストを設定することもできます。手順は、次のとおりです。1. ログインしないでアプリケーションを開始します。2. ログイン画面で [設定] をタップするか、上部のナビゲーションバーの「ギア」アイコン をタップしま

す。3. [接続を選択] 画面で、プラスアイコン をタップします。4. (省略可能ですが推奨) 今後アクセスしたときにこの設定を簡単に識別できるように、表示ラベルを入力し

ます。5. カスタムログインホストの URI を入力します。必ず https://プレフィックスを削除してください。次に、

一般的なコミュニティ URI の入力方法の例を示します。mycommunity-developer-edition.na15.force.com/fineapps

363

ログインエンドポイントを設定するMobile SDK アプリケーションでの Communities の使用

コミュニティのブランド設定

エディション

使用可能なエディション:Salesforce Classic

使用可能なエディション:Enterprise Edition、Performance Edition、Unlimited Edition、およびDeveloper Edition

ユーザ権限

コミュニティを作成、カスタマイズ、有効化する• 「コミュニティの作成

および設定」

および

アクセスしようとする[コミュニティ管理]ページのコミュニティメンバーである

Salesforceタブ + Visualforceテンプレートを使用している場合は、会社のロゴ、色、著作権表示を追加して、コミュニティ管理でコミュニティのデザインをカスタマイズできます。これにより、コミュニティが会社のブランド設定と一致し、コミュニティメンバーがただちに認識できるようになります。

重要: セルフサービステンプレートを使用しているか、カスタムページを作成するために標準 Salesforce タブではなくコミュニティビルダーを選択した場合は、コミュニティビルダーを使用してコミュニティのブランド設定を行うこともできます。

1. 次のいずれかの方法で、コミュニティ管理にアクセスします。• コミュニティからアクセスする場合

– Salesforce タブ + Visualforce コミュニティで、グローバルヘッダーのをクリックします。

– コミュニティビルダーベースのコミュニティで、名前の横にあるドロップダウンメニューを使用して [コミュニティ管理] をクリックします。

• [設定] から、[クイック検索] ボックスに「すべてのコミュニティ」と入力し、[すべてのコミュニティ]を選択してコミュニティの横にある[管理]リンクをクリックします。

• コミュニティビルダーのヘッダーで、テンプレートの名前の横にあるドロップダウンメニューを使用して[コミュニティ管理]をクリックします。

2. [管理] > [ブランド] をクリックします。3. ルックアップを使用して、コミュニティのヘッダーとフッターを選択します。

ヘッダーとフッター用に選択するファイルは、[ドキュメント] タブにアップロード済みで、公開されている必要があります。ヘッダーには、.html、.gif、.jpg、または .png を使用できます。フッターは、.html ファイルである必要があります。.html ファイルの合計最大サイズは 100 KB です。.gif、.jpg、または .png ファイルの最大サイズは 20 KB です。このため、ヘッダーの .html ファイルが 70 KB で、.html ファイルをフッターにも使用する場合は、30 KB 以内にする必要があります。選択したヘッダーは、グローバルヘッダーの下にある Salesforce ロゴに置き換わります。選択したフッターは、Salesforce 標準の著作権とプライバシーのフッターに置き換わります。

4. [配色を選択] をクリックして事前定義された配色を選択するか、ページ選択項目の横にあるテキストボックスをクリックしてカラーピッカーから色を選択します。選択した色の中には、コミュニティのログインページと、Salesforce1のコミュニティの外観にも影響を与えるものもあります。

364

コミュニティのブランド設定Mobile SDK アプリケーションでの Communities の使用

表示場所色の選択肢

黒のグローバルヘッダーの下のページ上部。[ヘッダー] 項目で HTML ファイルを選択した場合は、この色が上書きされます。ログインページ上部。

ヘッダー背景

Salesforce1 のログインページ。

ログインページを含む、コミュニティのすべてのページの背景色。ページ背景

選択されたタブ。プライマリ

リストとテーブルの上境界線。ログインページのボタン。

セカンダリ

編集と詳細ページのセクションヘッダーの背景色。ターティアリ

5. [保存] をクリックします。

コミュニティのログイン、ログアウト、およびセルフ登録ページのカスタマイズ

エディション

使用可能なエディション:Salesforce Classic

使用可能なエディション:Enterprise Edition、Performance Edition、Unlimited Edition、およびDeveloper Edition

ユーザ権限

コミュニティを作成、カスタマイズ、有効化する• 「コミュニティの作成

および設定」

および

アクセスしようとする[コミュニティ管理]ページのコミュニティメンバーである

コミュニティの標準のログイン、ログアウト、パスワード管理、およびセルフ登録オプションを設定したり、Apex、Visualforce、またはコミュニティビルダー(Site.com Studio) ページの動作をカスタマイズしたりします。デフォルトでは、各コミュニティには、デフォルトのログイン、パスワード管理、およびセルフ登録ページと、内部でこの機能を操作する関連Apexコントローラが付属します。Visualforce、Apex、またはコミュニティビルダー (Site.com Studio)

を使用して、カスタムのブランド設定を作成したり、デフォルトの動作を変更したりできます。• デフォルトのログインページのブランド設定をカスタマイズする。• デフォルトのログインページ動作の変更、カスタムログインページの使用、

他の認証プロバイダのサポートを行うことで、ログイン環境をカスタマイズする。

• ログアウト時にユーザを異なる URL にリダイレクトする。• [パスワードの変更] および [パスワードを忘れた場合] カスタムページを使用

する。• コミュニティでライセンスのないゲストユーザに対してセルフ登録を設定す

る。

365

コミュニティのログイン、ログアウト、およびセルフ登録ページのカスタマイズ

Mobile SDK アプリケーションでの Communities の使用

コミュニティでの外部認証の使用

Facebook©などの外部認証プロバイダを使用して、コミュニティユーザを Mobile SDK アプリケーションにログインさせることができます。

メモ: Salesforce では、Janrain を認証プロバイダとして使用できますが、これは基本的に Salesforce で内部的に使用することを目的としています。ここで Janrain を説明した理由は、すべての情報を網羅するためです。

外部認証プロバイダについてエディション

使用可能なエディション:Lightning Experience およびSalesforce Classic

使用可能なエディション:Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、およびDeveloper Edition

ユーザ権限

設定を参照する• 「設定・定義を参照す

る」

設定を編集する• 「アプリケーションの

カスタマイズ」

および

「認証プロバイダの管理」

Facebook©、Janrain©などの外部サービスプロバイダのログイン情報を使用して、Salesforce 組織にユーザがログインできるようにできます。シングルサインオン用認証プロバイダを正常に設定するには、次の操作を実行します。• サービスプロバイダの Web サイトを正しく設定する。• Apex を使用して登録ハンドラを作成する。• 組織の認証プロバイダを定義する。設定が完了すると、認証プロバイダフローは次のようになります。1. ユーザがサードパーティ ID を使用してSalesforceにログインしようとします。2. ログイン要求はサードパーティの認証プロバイダにリダイレクトされます。3. ユーザはサードパーティログインプロセスに従い、アクセスを承認します。4. サードパーティ認証プロバイダは認証情報と共にユーザをSalesforceにリダイ

レクトします。5. ユーザは Salesforce にサインインされます。

メモ: ユーザが既存の Salesforce セッションを持つ場合、サードパーティでの認証後、Salesforce アカウントへのリンクを承認できるページに自動的にリダイレクトされます。

認証プロバイダの定義次のプロバイダをサポートしています。• Facebook

• Google

• Janrain

• LinkedIn

• Microsoft アクセスコントロールサービス• Salesforce

• Twitter

• OpenID Connect プロトコルを実装しているサービスプロバイダ

366

コミュニティでの外部認証の使用Mobile SDK アプリケーションでの Communities の使用

認証プロバイダへの機能の追加追加の要求パラメータを使用して、認証プロバイダに機能を追加できます。• Scope – サードパーティから要求された権限をカスタマイズする• Site – プロバイダをサイトで使用可能にする• StartURL – 認証後にユーザを指定された場所に送信する• Community – 認証後にユーザを特定のコミュニティに送信する• 認証エンドポイント – ユーザを認証のために特定の認証エンドポイントに送信する (Salesforce 認証プロバイ

ダのみ)

Apex 登録ハンドラの作成登録ハンドラクラスはシングルサインオンフロー用の認証プロバイダを使用する必要があります。Apex登録ハンドラクラスでは Auth.RegistrationHandlerインターフェースを実装する必要があります。このインターフェースでは 2 つのメソッドを定義します。Salesforceでは、ユーザがこのプロバイダを以前使用したかどうかに応じて、コールバックで適切なメソッドを起動します。認証プロバイダを作成する場合、テストのためにApex テンプレートクラスを自動的に作成できます。

コミュニティ URL パラメータの使用エディション

使用可能なエディション:Lightning Experience およびSalesforce Classic

使用可能なエディション:Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、およびDeveloper Edition

ユーザ権限

設定を参照する• 「設定・定義を参照す

る」

設定を編集する• 「アプリケーションの

カスタマイズ」

および

「認証プロバイダの管理」

認証後に、ユーザを特定のコミュニティに送信します。認証後にユーザを特定のコミュニティに転送するには、community 要求パラメータで URL を指定する必要があります。パラメータを追加しない場合、ユーザは認証完了後に /home/home.jsp (ポータルまたは標準アプリケーションの場合) またはデフォルトのサイトページ (サイトの場合) に送信されます。

例: たとえば、[シングルサインオン初期化 URL] では、ユーザはログイン後にこの場所に送信されます。[既存ユーザをリンクする URL] では、確認ページの [Salesforce に進む] リンクによってこのページに送信されます。次に、[シングルサインオン初期化 URL]に追加される communityパラメータの例を示します。ここで、• orgID は、認証プロバイダ ID です。• URLsuffix は、認証プロバイダを定義したときに指定した値です。https://login.salesforce.com/services/auth/sso/orgID/URLsuffix?community=https://acme.force.com/support

367

コミュニティ URL パラメータの使用Mobile SDK アプリケーションでの Communities の使用

Scope パラメータの使用エディション

使用可能なエディション:Lightning Experience およびSalesforce Classic

使用可能なエディション:Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、およびDeveloper Edition

ユーザ権限

設定を参照する• 「設定・定義を参照す

る」

設定を編集する• 「アプリケーションの

カスタマイズ」

および

「認証プロバイダの管理」

返されたアクセストークンが追加権限を持つように、Facebook や Janrain などのサードパーティから要求された権限をカスタマイズします。サードパーティへの要求をカスタマイズして、追加権限を持つアクセストークンを受け取ることができます。その後、Auth.AuthToken メソッドを使用して、付与されたアクセストークンを取得し、これらの権限をサードパーティで使用することができます。デフォルトの範囲はサードパーティによって異なりますが、一般に、基本的なユーザ情報を超える情報へのアクセスは許可されません。各プロバイダタイプ(Open ID Connect、Facebook、Salesforce など) には、要求と共に認証エンドポイントに送信するデフォルトの範囲のセットがあります。たとえば、Salesforceのデフォルトの範囲は id です。範囲は、スペースで区切られた文字列で送信できます。要求された範囲の空白で区切られた文字列がそのままでサードパーティに送信され、認証プロバイダによって要求されたデフォルトの権限を上書きします。Janrain ではこのパラメータを使用しないため、Janrain 内で追加の権限を設定する必要があります。

例: 次に、[シングルサインオン初期化 URL] に追加される、Salesforce の範囲 apiおよびwebを要求する scopeパラメータの例を示します。ここで、• orgID は、認証プロバイダ ID です。• URLsuffix は、認証プロバイダを定義したときに指定した値です。https://login.salesforce.com/services/auth/sso/orgID/URLsuffix?scope=id%20api%20web

有効な範囲はサードパーティによって異なるため、個々のサードパーティのドキュメントを参照してください。たとえば、Salesforce の範囲は次のようになります。

説明値

REST API や Bulk API などの API を使用して、現在のログインユーザの取引先へのアクセスを許可します。この値には、Chatter REST APIリソースへのアクセスを許可する chatter_api も含まれます。

api

Chatter REST API リソースへのアクセスのみを許可します。chatter_api

接続アプリケーションに関連付けられている組織のカスタム権限へのアクセスを許可し、現在のユーザで各権限が有効かどうかを示します。

custom_permissions

ログインユーザがアクセスできるすべてのデータへのアクセスを許可し、その他すべての範囲が対象となります。full は更新トークンを返しません。更新トー

full

クンを取得するには、refresh_token の範囲を明示的に要求する必要があります。

368

Scope パラメータの使用Mobile SDK アプリケーションでの Communities の使用

説明値

ID URL サービスへのアクセスを許可します。profile、email、address、phone

を要求すれば、id を使用した場合と同じ結果を個別に得られます。これらの結果はすべて一致します。

id

OpenID Connect アプリケーションの現在のログインユーザの一意の識別子へのアクセスを許可します。アクセストークンの他にも、「OpenID Connect の仕様」に従って、OAuth 2.0 ユーザエージェントフローおよび OAuth 2.0 Web サーバ認証フローで openid 範囲を使用して、署名付き ID トークンを再度取得できます。

openid

更新トークンを受信できる場合に、それを返すように指定します。これにより、ユーザがオフラインのときにアプリケーションがユーザのデータを操作できます。これは、offline_access を要求した場合と同じ意味になります。

refresh_token

Visualforce ページへのアクセスを許可します。visualforce

Web で access_token を使用することを許可します。これには visualforce

も含まれ、Visualforce ページへのアクセスが許可されます。web

369

Scope パラメータの使用Mobile SDK アプリケーションでの Communities の使用

Facebook 認証プロバイダの設定エディション

使用可能なエディション:Lightning Experience およびSalesforce Classic

使用可能なエディション:Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、およびDeveloper Edition

ユーザ権限

設定を参照する• 「設定・定義を参照す

る」

設定を編集する• 「アプリケーションの

カスタマイズ」

および

「認証プロバイダの管理」

Facebook を認証プロバイダとして使用する手順は、次のとおりです。1. Facebook アプリケーションを設定し、Salesforce をアプリケーションのドメイ

ンにします。2. Salesforce 組織の Facebook 認証プロバイダを定義します。3. Salesforce によって生成される [コールバック URL] を Facebook の [Web サイ

トの URL] として使用するように、Facebook アプリケーションを更新します。

4. 接続をテストします。

Facebook アプリケーションの設定Salesforce組織で Facebook を設定するには、次の手順で Facebook でアプリケーションを設定する必要があります。

メモ: Salesforceに Google 独自のデフォルトアプリケーションの使用を許可すると、この手順を省略できます。詳細は、「Salesforce 管理値を使用した認証プロバイダの設定」を参照してください。

1. Facebook の Web サイトに移動して、新しいアプリケーションを作成します。2. アプリケーション設定を変更し、アプリケーションドメインをSalesforceに設

定します。3. アプリケーション ID とアプリケーションシークレットを確認します。

Salesforce 組織での Facebook プロバイダの定義Salesforce組織で Facebook プロバイダを設定するには Facebook のアプリケーション ID とアプリケーションシークレットが必要です。

メモ: Salesforce に値の管理を許可すると、プロバイダ設定の主要な値の指定を省略できます。詳細は、「Salesforce 管理値を使用した認証プロバイダの設定」を参照してください。

1. [設定] から、[クイック検索] ボックスに「認証プロバイダ」と入力し、[認証プロバイダ] を選択します。2. [新規] をクリックします。3. [プロバイダタイプ] には Facebook を選択します。4. プロバイダの [名前] を入力します。5. [URL 接尾辞] を入力します。これは、クライアント設定 URL で使用されます。たとえば、プロバイダの

URL サフィックスが「MyFacebookProvider」である場合、シングルサインオン URL はhttps://login.salesforce.com/auth/sso/00Dx00000000001/MyFacebookProviderのようになります。

6. [コンシューマ鍵] 項目には、Facebook のアプリケーション ID を使用します。7. [コンシューマの秘密] 項目には、Facebook のアプリケーションシークレットを使用します。

370

Facebook 認証プロバイダの設定Mobile SDK アプリケーションでの Communities の使用

8. 必要に応じて、次の項目を設定します。a. [承認エンドポイント URL] に Facebook から入手したベース URL を入力します。たとえば、

https://www.facebook.com/v2.2/dialog/oauth です。この項目を空白のままにした場合は、アプリケーションが使用する Facebook API のバージョンが使用されます。

ヒント: 必要に応じて、クエリ文字列パラメータをベース URL に追加できます。たとえば、オフラインアクセス用に Google から更新トークンを取得するには、https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force

を使用します。この例では、更新アクションの承認をユーザに求めるには追加のapproval_prompt

パラメータが必要となるため、Google では最初の更新トークンの後にも更新トークンが引き続き提供されます。

b. Facebook から入手した [トークンエンドポイント URL] を入力します。たとえば、https://www.facebook.com/v2.2/dialog/oauth です。この項目を空白のままにした場合は、アプリケーションが使用する Facebook API のバージョンが使用されます。

c. Facebook のプロファイル API から要求された値を変更する場合は、[ユーザ情報エンドポイント URL] を入力します。項目についての詳細は、https://developers.facebook.com/docs/facebook-login/permissions/v2.0#reference-public_profileを参照してください。要求された項目は、要求された範囲に対応する必要があります。この項目を空白のままにした場合は、アプリケーションが使用する Facebook API のバージョンが使用されます。

d. 認証エンドポイントへの要求と共に送信する [デフォルトの範囲]。送信しない場合は、プロバイダタイプのハードコード化されたデフォルトが使用されます (デフォルトについてはFacebook の開発者向けドキュメントを参照)。詳細は、「Scope パラメータの使用」を参照してください。

e. エラーのレポートに使用するプロバイダの [カスタムエラー URL]。f. ユーザがシングルサインオンフローを使用して認証された場合に、ログアウト後の特定の移動先を指定

する [カスタムログアウト URL]。この項目を使用して、ユーザをブランド設定されたログアウトページか、またはデフォルトの Salesforce ログアウトページ以外の場所のいずれかに移動します。URL は、httpまたは httpsプレフィックスで完全修飾する必要があります (https://acme.my.salesforce.com

など)。g. 既存のApexクラスを [登録ハンドラ]クラスとして選択するか、[登録ハンドラテンプレートを自動作成]

をクリックして、登録ハンドラのApexクラステンプレートを作成します。このクラスを編集してデフォルトのコンテンツを変更してから使用する必要があります。

メモ: Salesforceの登録ハンドラクラスを指定して、[シングルサインオン初期化 URL] を生成する必要があります。

h. [他のアカウントで登録を実行] で Apex ハンドラクラスを実行するユーザを選択します。このユーザは「ユーザの管理」権限を持っている必要があります。登録ハンドラを選択した場合、または登録ハンドラを自動作成する場合にはユーザが必要です。

i. プロバイダでポータルを使用するには、[ポータル] ドロップダウンリストからポータルを選択します。j. [アイコン URL] 項目を使用して、コミュニティのログインページのボタンとして表示するアイコンの

パスを追加します。このアイコンは、コミュニティにのみ適用され、Salesforce 組織のログインページ

371

Facebook 認証プロバイダの設定Mobile SDK アプリケーションでの Communities の使用

や、[私のドメイン] で作成されたカスタムドメインのログインページには表示されません。ユーザは、このボタンをクリックし、コミュニティに関連付けられた認証プロバイダを使用してログインします。独自の画像へのパスを指定することも、いずれかのサンプルアイコンの URL を項目にコピーすることもできます。

9. [保存] をクリックします。生成された [認証プロバイダ ID] の値を確認しておいてください。この値は、Auth.AuthToken Apex クラスと共に使用する必要があります。認証プロバイダを定義した後、複数のクライアント設定 URL が生成されます。• テスト専用初期化 URL: システム管理者は、この URL を使用して、サードパーティプロバイダが正しく設定

されていることを確認します。システム管理者がこの URL をブラウザで開き、サードパーティにサインインすると、属性の対応付けと共に Salesforce にリダイレクトされます。

• シングルサインオン初期化 URL: この URL を使用して、サードパーティから Salesforce にシングルサインオンを実行します (サードパーティの認証情報が使用されます)。エンドユーザは、この URL をブラウザで開き、サードパーティにサインインします。エンドユーザの新規ユーザを作成するか、既存のユーザを更新してから、そのユーザとして Salesforce にサインインします。

• 既存ユーザをリンクする URL: この URL を使用して、既存の Salesforce ユーザをサードパーティアカウントにリンクします。エンドユーザは、この URL をブラウザで開き、サードパーティにサインインして Salesforce

にサインインし、リンクを承認します。• Oauth 専用初期化 URL: この URL を使用して、サードパーティの OAuth アクセストークンを取得します。

サードパーティサービスでトークンを取得するには、ユーザは Salesforce の認証を受ける必要があります。このフローでは、以降のシングルサインオン機能は提供されません。

• コールバック URL: 認証プロバイダが設定のためにコールバックするエンドポイントに、コールバック URL

を使用します。認証プロバイダは、前述の各クライアント設定 URL の情報と共に、[コールバック URL] にリダイレクトする必要があります。

クライアント設定 URL では、ユーザの特定サイトへのログイン、サードパーティからのカスタマイズされた権限の取得、認証後の特定の場所への移動を行うための、追加の要求パラメータをサポートしています。

Facebook アプリケーションの更新Facebook 認証プロバイダを Salesforce 組織に定義したら、Facebook に戻り、[コールバック URL] を Facebook の[Web サイトの URL] として使用するようにアプリケーションを更新します。

シングルサインオン接続のテストブラウザの認証プロバイダの詳細ページで [テスト専用初期化 URL] を開きます。このページによりユーザはFacebook にリダイレクトされ、サインインするよう求められます。サインイン時に、アプリケーションを認証する求められます。認証後、ユーザは Salesforce にリダイレクトされます。

372

Facebook 認証プロバイダの設定Mobile SDK アプリケーションでの Communities の使用

Salesforce 認証プロバイダの設定エディション

使用可能なエディション:Lightning Experience およびSalesforce Classic

使用可能なエディション:Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、およびDeveloper Edition

ユーザ権限

設定を参照する• 「設定・定義を参照す

る」

設定を編集する• 「アプリケーションの

カスタマイズ」

および

「認証プロバイダの管理」

接続アプリケーションを認証プロバイダとして使用できます。1. 接続アプリケーションを定義します。2. 組織の Salesforce 認証プロバイダを定義します。3. 接続をテストします。

接続アプリケーションの定義Salesforce 組織の Salesforce プロバイダを設定する前に、シングルサインオンを使用する接続アプリケーションを定義する必要があります。[設定] から、[クイック検索] ボックスに「アプリケーション」と入力し、[アプリケーション] を選択します。接続アプリケーションの定義の完了後は、[コンシューマ鍵] 項目および [コンシューマの秘密] 項目の値を保存します。

メモ: Salesforceに Google 独自のデフォルトアプリケーションの使用を許可すると、この手順を省略できます。詳細は、「Salesforce 管理値を使用した認証プロバイダの設定」を参照してください。

組織の Salesforce 認証プロバイダの定義組織の認証プロバイダを設定するには、接続アプリケーション定義の[コンシューマ鍵] 項目および [コンシューマの秘密] 項目の値が必要です。

メモ: Salesforceに値の管理を許可すると、プロバイダ設定の主要な値の指定を省略できます。詳細は、「Salesforce 管理値を使用した認証プロバイダの設定」を参照してください。

1. [設定] から、[クイック検索] ボックスに「認証プロバイダ」と入力し、[認証プロバイダ] を選択します。2. [新規] をクリックします。3. [プロバイダタイプ] には Salesforce を選択します。4. プロバイダの [名前] を入力します。5. [URL 接尾辞] を入力します。これは、クライアント設定 URL で使用されます。たとえば、プロバイダの

URL サフィックスが「MySFDCProvider」である場合、シングルサインオン URL はhttps://login.salesforce.com/auth/sso/00Dx00000000001/MySFDCProvider のようになります。

6. 接続アプリケーション定義の [コンシューマ鍵] 項目の値を [コンシューマ鍵] 項目に貼り付けます。7. 接続アプリケーション定義の [コンシューマの秘密] 項目の値を [コンシューマの秘密] 項目に貼り付けま

す。8. 必要に応じて、次の項目を設定します。

a. OAuth 認証の URL を指定するための [承認エンドポイント URL]。

373

Salesforce 認証プロバイダの設定Mobile SDK アプリケーションでの Communities の使用

[承認エンドポイント URL]の場合、ホスト名に Sandboxやカスタムドメイン名 ([私のドメイン] を使用して作成) を含めることができますが、URL は .salesforce.com で終わり、パスは/services/oauth2/authorize で終わる必要があります。たとえば、「https://login.salesforce.com/services/oauth2/authorize」などです。

b. OAuth トークンの URL を指定するための [トークンエンドポイント URL]。[トークンエンドポイント URL] の場合、ホスト名に Sandboxやカスタムドメイン名 ([私のドメイン] を使用して作成) を含めることができますが、URL は .salesforce.com で終わり、パスは/services/oauth2/token で終わる必要があります。たとえば、「https://login.salesforce.com/services/oauth2/token」などです。

c. 認証エンドポイントへの要求と共に送信する [デフォルトの範囲]。送信しない場合は、ハードコード化されたデフォルトが使用されます。詳細は、「Scope パラメータの使用」を参照してください。

メモ: 既存の Salesforce認証プロバイダの設定を編集する場合、サードパーティアカウントのリンクの組織 ID を含むようにチェックボックスをオンにできることがあります。Summer '14 リリース以前に設定された Salesforce 認証プロバイダでは、組織が提供するユーザ ID に組織 ID が含まれません。そのため、対象組織は 2 つのソース (2 つの Sandbox など) の同じユーザ ID を持つユーザを区別できません。(各 Sandbox から 1 人の) 2 人のユーザが対象組織で同じユーザに対応付けられている既存の組織があり、ID を別にする場合は、このチェックボックスをオンにします。そうでない場合は、このチェックボックスをオフのままにします。この機能を有効にした後に、ユーザはすべてのサードパーティのリンクの連結を再承認する必要があります。これらのリンクは、ユーザの詳細ページの[サードパーティアカウントのリンク] セクションに一覧表示されます。Winter '15 リリース以降に作成されたSalesforce認証プロバイダは、デフォルトでこの設定が有効になり、チェックボックスは表示されません。

d. エラーのレポートに使用するプロバイダの [カスタムエラー URL]。e. ユーザがシングルサインオンフローを使用して認証された場合に、ログアウト後の特定の移動先を指定

する [カスタムログアウト URL]。この項目を使用して、ユーザをブランド設定されたログアウトページか、またはデフォルトの Salesforce ログアウトページ以外の場所のいずれかに移動します。URL は、httpまたは httpsプレフィックスで完全修飾する必要があります (https://acme.my.salesforce.com

など)。

9. 既存の Apexクラスを [登録ハンドラ] クラスとして選択するか、[登録ハンドラテンプレートを自動作成] をクリックして、登録ハンドラのApexクラスを作成します。このテンプレートクラスを使用する前に、編集してデフォルトのコンテンツを変更する必要があります。

メモ: Salesforce の登録ハンドラクラスを指定して、[シングルサインオン初期化 URL] を生成する必要があります。

10. [他のアカウントで登録を実行]でApexハンドラクラスを実行するユーザを選択します。このユーザは「ユーザの管理」権限を持っている必要があります。登録ハンドラを選択した場合、または登録ハンドラを自動作成する場合にはユーザが必要です。

11. プロバイダでポータルを使用するには、[ポータル] ドロップダウンリストからポータルを選択します。

374

Salesforce 認証プロバイダの設定Mobile SDK アプリケーションでの Communities の使用

12. [アイコン URL]項目を使用して、コミュニティのログインページのボタンとして表示するアイコンのパスを追加します。このアイコンは、コミュニティにのみ適用され、Salesforce 組織のログインページや、[私のドメイン] で作成されたカスタムドメインのログインページには表示されません。ユーザは、このボタンをクリックし、コミュニティに関連付けられた認証プロバイダを使用してログインします。独自の画像へのパスを指定することも、いずれかのサンプルアイコンの URL を項目にコピーすることもできます。

13. [保存] をクリックします。クライアント設定 URL の値を確認します。最後のステップを完了するには [コールバック URL] が必要です。また、[テスト専用初期化 URL] を使用して、設定をチェックします。Auth.AuthToken Apex クラスと共に [認証プロバイダ ID] 値を使用する必要があるため、その値を確認しておく必要もあります。

14. 前のステップで作成した接続アプリケーション定義に戻り ([設定] の [アプリケーション] ページで接続アプリケーション名をクリックする)、認証プロバイダの [コールバック URL] の値を [コールバック URL] 項目に貼り付けます。

認証プロバイダを定義した後、複数のクライアント設定 URL が生成されます。• テスト専用初期化 URL: システム管理者は、この URL を使用して、サードパーティプロバイダが正しく設定

されていることを確認します。システム管理者がこの URL をブラウザで開き、サードパーティにサインインすると、属性の対応付けと共に Salesforce にリダイレクトされます。

• シングルサインオン初期化 URL: この URL を使用して、サードパーティから Salesforce にシングルサインオンを実行します (サードパーティの認証情報が使用されます)。エンドユーザは、この URL をブラウザで開き、サードパーティにサインインします。エンドユーザの新規ユーザを作成するか、既存のユーザを更新してから、そのユーザとして Salesforce にサインインします。

• 既存ユーザをリンクする URL: この URL を使用して、既存の Salesforce ユーザをサードパーティアカウントにリンクします。エンドユーザは、この URL をブラウザで開き、サードパーティにサインインして Salesforce

にサインインし、リンクを承認します。• Oauth 専用初期化 URL: この URL を使用して、サードパーティの OAuth アクセストークンを取得します。

サードパーティサービスでトークンを取得するには、ユーザは Salesforce の認証を受ける必要があります。このフローでは、以降のシングルサインオン機能は提供されません。

• コールバック URL: 認証プロバイダが設定のためにコールバックするエンドポイントに、コールバック URL

を使用します。認証プロバイダは、前述の各クライアント設定 URL の情報と共に、[コールバック URL] にリダイレクトする必要があります。

クライアント設定 URL では、ユーザの特定サイトへのログイン、サードパーティからのカスタマイズされた権限の取得、認証後の特定の場所への移動を行うための、追加の要求パラメータをサポートしています。

シングルサインオン接続のテストブラウザの認証プロバイダの詳細ページで [テスト専用初期化 URL] を開きます。

375

Salesforce 認証プロバイダの設定Mobile SDK アプリケーションでの Communities の使用

OpenID Connect 認証プロバイダの設定エディション

使用可能なエディション:Lightning Experience およびSalesforce Classic

使用可能なエディション:Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、およびDeveloper Edition

ユーザ権限

設定を参照する• 「設定・定義を参照す

る」

設定を編集する• 「アプリケーションの

カスタマイズ」

および

「認証プロバイダの管理」

Amazon、Google、PayPal など、OpenID Connect プロトコルのサーバ側を実装するサードパーティの Web アプリケーションを認証プロバイダとして使用できます。OpenID 認証プロバイダを設定するには、次の手順を実行します。1. アプリケーションを登録して、Salesforce をアプリケーションドメインにしま

す。2. Salesforce 組織の OpenID Connect 認証プロバイダを定義します。3. Salesforce によって生成される [コールバック URL] をコールバック URL とし

て使用するように、アプリケーションを更新します。4. 接続をテストします。

OpenID Connect アプリケーションの登録Salesforce組織の Web アプリケーションを設定する前に、アプリケーションをサービスプロバイダに登録する必要があります。このプロセスは、サービスプロバイダによって異なります。たとえば、Google アプリケーションを登録するには、OAuth 2.0 クライアント ID を作成します。1. サービスプロバイダの Web サイトにアプリケーションを登録します。2. アプリケーション設定を変更し、アプリケーションドメイン (または [ホーム

ページの URL]) を Salesforce に設定します。3. プロバイダのドキュメントに記載されている、クライアント ID とクライアン

トの秘密、承認エンドポイント URL、トークンエンドポイント URL、ユーザ情報エンドポイント URL をメモします。一般的な OpenID Connect サービスプロバイダとして、次のようなプロバイダがあります。• Amazon

• Google

• PayPal

Salesforce 組織の OpenID Connect プロバイダの定義Salesforce 組織のアプリケーションを設定するには、プロバイダからの情報 (クライアント ID とクライアントの秘密、承認エンドポイント URL、トークンエンドポイント URL、ユーザ情報エンドポイント URL) が必要です。1. [設定] から、[クイック検索] ボックスに「認証プロバイダ」と入力し、[認証プロバイダ] を選択します。2. [新規] をクリックします。3. [プロバイダタイプ] では [OpenID Connect] を選択します。4. プロバイダの [名前] を入力します。5. [URL 接尾辞] を入力します。これは、クライアント設定 URL で使用されます。たとえば、プロバイダの

URL サフィックスが「MyOpenIDConnectProvider」である場合、シングルサインオン URL は

376

OpenID Connect 認証プロバイダの設定Mobile SDK アプリケーションでの Communities の使用

https://login.salesforce.com/auth/sso/00Dx00000000001/MyOpenIDConnectProviderのようになります。

6. [コンシューマ鍵] 項目には、プロバイダから入手したクライアント ID を使用します。7. [コンシューマの秘密] 項目には、プロバイダから入手したクライアントの秘密を使用します。8. [承認エンドポイント URL] には、プロバイダから入手したベース URL を入力します。

ヒント: 必要に応じて、クエリ文字列パラメータをベース URL に追加できます。たとえば、オフラインアクセス用に Google から更新トークンを取得するには、https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force

を使用します。この場合、更新アクションの承認をユーザに求めるには追加の approval_promptパラメータが必要となるため、Google では最初の更新トークンの後にも更新トークンが引き続き提供されます。

9. プロバイダから入手した [トークンエンドポイント URL] を入力します。10. 必要に応じて、次の項目を設定します。

a. プロバイダから入手した [ユーザ情報エンドポイント URL]。b. [トークン発行者]。この値には、認証トークンのソースを https: URL形式で指定します。この値が指

定された場合、プロバイダはトークン要求への応答に id_token値を含める必要があります。id_token

値は更新トークンフローでは必要ありません (ただし、指定された場合は Salesforce によって検証されます)。

c. 認証エンドポイントへの要求と共に送信する [デフォルトの範囲]。送信しない場合は、プロバイダタイプのハードコード化されたデフォルトが使用されます (デフォルトについてはOpenID Connect の開発者用ドキュメントを参照)。詳細は、「Scope パラメータの使用」を参照してください。

11. [ヘッダーでアクセストークンを送信] を選択すると、トークンをクエリ文字列ではなくヘッダーに送信できます。

12. 必要に応じて、次の項目を設定します。a. エラーのレポートに使用するプロバイダの [カスタムエラー URL]。b. ユーザがシングルサインオンフローを使用して認証された場合に、ログアウト後の特定の移動先を指定

する [カスタムログアウト URL]。この項目を使用して、ユーザをブランド設定されたログアウトページか、またはデフォルトの Salesforce ログアウトページ以外の場所のいずれかに移動します。URL は、httpまたは httpsプレフィックスで完全修飾する必要があります (https://acme.my.salesforce.com

など)。c. 既存のApexクラスを [登録ハンドラ]クラスとして選択するか、[登録ハンドラテンプレートを自動作成]

をクリックして、登録ハンドラのApexクラステンプレートを作成します。このクラスを編集してデフォルトのコンテンツを変更してから使用する必要があります。

メモ: Salesforceの登録ハンドラクラスを指定して、[シングルサインオン初期化 URL] を生成する必要があります。

377

OpenID Connect 認証プロバイダの設定Mobile SDK アプリケーションでの Communities の使用

d. [他のアカウントで登録を実行] で Apex ハンドラクラスを実行するユーザを選択します。このユーザは「ユーザの管理」権限を持っている必要があります。登録ハンドラを選択した場合、または登録ハンドラを自動作成する場合にはユーザが必要です。

e. プロバイダでポータルを使用するには、[ポータル] ドロップダウンリストからポータルを選択します。f. [アイコン URL] 項目を使用して、コミュニティのログインページのボタンとして表示するアイコンの

パスを追加します。このアイコンは、コミュニティにのみ適用され、Salesforce 組織のログインページや、[私のドメイン] で作成されたカスタムドメインのログインページには表示されません。ユーザは、このボタンをクリックし、コミュニティに関連付けられた認証プロバイダを使用してログインします。独自の画像へのパスを指定することも、いずれかのサンプルアイコンの URL を項目にコピーすることもできます。

13. [保存] をクリックします。生成された [認証プロバイダ ID] の値を確認しておいてください。この値は、Auth.AuthToken Apex クラスと共に使用する必要があります。認証プロバイダを定義した後、複数のクライアント設定 URL が生成されます。• テスト専用初期化 URL: システム管理者は、この URL を使用して、サードパーティプロバイダが正しく設定

されていることを確認します。システム管理者がこの URL をブラウザで開き、サードパーティにサインインすると、属性の対応付けと共に Salesforce にリダイレクトされます。

• シングルサインオン初期化 URL: この URL を使用して、サードパーティから Salesforce にシングルサインオンを実行します (サードパーティの認証情報が使用されます)。エンドユーザは、この URL をブラウザで開き、サードパーティにサインインします。エンドユーザの新規ユーザを作成するか、既存のユーザを更新してから、そのユーザとして Salesforce にサインインします。

• 既存ユーザをリンクする URL: この URL を使用して、既存の Salesforce ユーザをサードパーティアカウントにリンクします。エンドユーザは、この URL をブラウザで開き、サードパーティにサインインして Salesforce

にサインインし、リンクを承認します。• Oauth 専用初期化 URL: この URL を使用して、サードパーティの OAuth アクセストークンを取得します。

サードパーティサービスでトークンを取得するには、ユーザは Salesforce の認証を受ける必要があります。このフローでは、以降のシングルサインオン機能は提供されません。

• コールバック URL: 認証プロバイダが設定のためにコールバックするエンドポイントに、コールバック URL

を使用します。認証プロバイダは、前述の各クライアント設定 URL の情報と共に、[コールバック URL] にリダイレクトする必要があります。

クライアント設定 URL では、ユーザの特定サイトへのログイン、サードパーティからのカスタマイズされた権限の取得、認証後の特定の場所への移動を行うための、追加の要求パラメータをサポートしています。

OpenID Connect アプリケーションの更新認証プロバイダを Salesforce 組織に定義したら、プロバイダに戻り、アプリケーションの [コールバック URL]

(Google では [承認済みリダイレクト URI]、PayPal では [戻り URL] とも呼ばれる) を更新します。

378

OpenID Connect 認証プロバイダの設定Mobile SDK アプリケーションでの Communities の使用

シングルサインオン接続のテストブラウザの認証プロバイダの詳細ページで [テスト専用初期化 URL] を開きます。これによりユーザはプロバイダのサービスにリダイレクトされ、サインインするよう求められます。サインインすると、アプリケーションを認証するように求められます。認証後、ユーザは再び Salesforce にリダイレクトされます。

例: Mobile SDK アプリケーションからアクセスできるようにコミュニティを設定する

Mobile SDK アプリケーションからログインできるようにコミュニティを設定する場合、注意が必要です。このチュートリアルでは、詳細と適切な順序を直接確認できます。モバイルアクセス用にコミュニティユーザを設定する場合、設定の順序と方法が成功を左右します。たとえば、取引先責任者が関連付けられていないユーザは、モバイルデバイスでログインできません。次に、留意すべき重要なガイドラインを示します。• 取引先に属する取引先責任者からのみユーザを作成します。ユーザを作成してから、後で取引先責任者に

関連付けることはできません。• 使用する取引先の所有者にロールを割り当てていることを確認してください。割り当てていない場合、ユー

ザがログインしようとするとエラーが発生します。• iOS アプリケーションでカスタムログインホストを定義する場合、必ず http[s]:// プレフィックスを削

除してください。プレフィックスは、実行時に iOS コアによって追加されます。明示的にプレフィックスを含めると、無効なアドレスになる可能性があります。

1. プロファイルに権限を追加する2. コミュニティを作成する3. コミュニティに API ユーザプロファイルを追加する4. 新しい取引先責任者およびユーザを作成する5. 新しいコミュニティログインをテストする

プロファイルに権限を追加する「API の有効化」および「Chatter の有効化」権限のあるプロファイルを作成します。1. [設定] から、[クイック検索] ボックスに「プロファイル」と入力し、[プロファイル] を選択します。2. [新規プロファイル] をクリックします。3. [既存のプロファイル] で、[Customer Community User (カスタマーコミュニティユーザ)] を選択します。4. [プロファイル名] に「FineApps API User」(FineApps API ユーザ) と入力します。5. [保存] をクリックします。6. [FineApps API User (FineApps API ユーザ)] ページで、[編集] をクリックします。7. [システム管理者権限] で、[API の有効化] および [Chatter を有効化] を選択します。

379

例: Mobile SDK アプリケーションからアクセスできるようにコミュニティを設定する

Mobile SDK アプリケーションでの Communities の使用

メモ: 「Chatter の有効化」権限がないユーザは、Salesforceのコミュニティに正常にログインした直後に「アクセス権がありません」エラーが表示されます。

8. [保存] をクリックします。

メモ: このチュートリアルではプロファイルを使用しますが、必要な権限がある権限セットを使用することもできます。

コミュニティを作成するコミュニティおよびコミュニティログイン URL を作成します。次の手順についての詳細は、Salesforce ヘルプの「Salesforce Communities の有効化」および「コミュニティの作成」を参照してください。1. [設定] から、[クイック検索] ボックスに「コミュニティ」と入力します。2. [すべてのコミュニティ] が表示されない場合、次の手順を実行します。

a. [コミュニティ設定] をクリックします。b. [コミュニティを有効化] を選択します。c. [ドメイン名] に一意のドメイン名 (fineapps.<あなたの名前>.force.com など) を入力します。d. [使用可能か調べる] をクリックして、ドメイン名がまだ使用されていないことを確認します。e. [保存] をクリックします。

3. [設定] から、[クイック検索] ボックスに「コミュニティ」と入力し、[すべてのコミュニティ] を選択します。

4. [新規コミュニティ] をクリックします。5. テンプレートを選択し、新しいコミュニティに「FineApps Users」 (FineApps ユーザ) という名前を付けま

す。6. サフィックス編集ボックスで、[URL] に「customers」(顧客) と入力します。

サフィックスが含まれる完全な URL が表示され、これがコミュニティの新しい URL になります。7. [コミュニティを作成] をクリックして、[コミュニティ管理に移動] をクリックします。

コミュニティに API ユーザプロファイルを追加するAPI ユーザプロファイルを [メンバー] ページのコミュニティ設定に追加します。1. [管理] > [メンバー] をクリックします。2. [検索] で、[すべて] を選択します。3. [選択可能なプロファイル] リストで [FineApps API ユーザ] を選択し、[追加] をクリックします。4. [保存] をクリックします。5. [公開] をクリックします。6. 確認ダイアログボックスを閉じて、[閉じる] をクリックします。

380

コミュニティを作成するMobile SDK アプリケーションでの Communities の使用

新しい取引先責任者およびユーザを作成するユーザを直接作成する代わりに、取引先の取引先責任者を作成した後でその取引先責任者からユーザを作成します。現在、取引先がない場合、次の手順を実行します。1. [取引先] タブをクリックします。2. 組織にまだ取引先がない場合、次の手順を実行します。

a. [簡易作成] の [取引先名] に「My Test Account」(私のテスト取引先) と入力します。b. [保存] をクリックします。

3. [最近の取引先] で、[My Test Account (私のテスト取引先)] またはその他の取引先名をクリックします。取引先所有者の名前をメモします。

4. [設定] から、[クイック検索]ボックスに「ユーザ」と入力し、[ユーザ]を選択して、取引先所有者名の横にある [編集] をクリックします。

5. [ロール] が CEO などの管理ロールに設定されていることを確認します。6. [保存] をクリックします。7. [取引先] タブをクリックして、取引先の名前を再度クリックします。8. [取引先責任者] で、[新規取引先責任者] をクリックします。9. [名] に「Jim」、[姓] に「Parker」と入力します。[保存] をクリックします。10. Jim Parker の [取引先責任者] ページで、[外部ユーザの管理]をクリックし、[カスタマーユーザを有効化]を選

択します。11. [ユーザライセンス] で、[Customer Community (カスタマーコミュニティ)] を選択します。12. [プロファイル] で、[FineApps API User (FineApps API ユーザ)]を選択します。13. その他の必須項目に次の値を使用します。

値項目

有効なメールアドレスを入力します。メール

[email protected]ユーザ名

jimmypニックネーム

必須でない情報は、ブラウザによって自動的に入力される場合は削除できます。14. [保存] をクリックします。15. Jim Parker への歓迎メールが受信箱に届くのを待ってから、そのメールのリンクをクリックしてパスワード

を作成します。パスワードを「mobile333」に設定します。

381

新しい取引先責任者およびユーザを作成するMobile SDK アプリケーションでの Communities の使用

新しいコミュニティログインをテストする新しい取引先責任者としてMobile SDKネイティブまたはハイブリッドローカルアプリケーションにログインし、コミュニティ設定をテストします。Mobile SDK アプリケーションからコミュニティにログインするには、コミュニティログイン URL を認識するようにアプリケーションを設定します。1. Android の場合:

a. Android Studio で Android プロジェクトを開きます。b. プロジェクトエクスプローラで、res フォルダに移動し、新しい xml フォルダを作成するか、既存の

フォルダを選択します。c. xmlフォルダで、テキストファイルを作成します。これは、[ファイル]メニューまたは Ctrl-クリック

(または右クリック) メニューを使用して行うことができます。d. 新しいテキストファイルで、次の XML を追加します。サーバ URL をコミュニティログイン URL で置き換

えます。<?xml version="1.0" encoding="utf-8"?><servers><server name="Community Login" url="https://fineapps-developer-edition.<instance>.force.com/fineapps"></servers>

e. ファイルを servers.xml として保存します。

2. iOS の場合:

a. ログインしないでアプリケーションを開始します。b. ログイン画面で [設定] をタップするか、上部のナビゲーションバーの「ギア」アイコン をタップし

ます。c. [接続を選択] 画面で、プラスアイコン をタップします。d. (省略可能ですが推奨) 今後アクセスしたときにこの設定を簡単に識別できるように、表示ラベルを入力

します。e. カスタムログインホストの URI を入力します。必ず https:// プレフィックスを削除してください。次

に、一般的なコミュニティ URI の入力方法の例を示します。mycommunity-developer-edition.na15.force.com/fineapps

または、設定に MDM を使用している場合、MDM を介してログイン画面を設定します。

3. デバイス、シミュレータ、またはエミュレータでアプリケーションを起動し、ユーザ名[email protected]、パスワード mobiletest1234 でログインします。

メモ: モバイルアプリケーションで長期間ログイン画面のままでいると、ログイン時に「アクセス権がありません」エラーが発生する可能性があります。この場合、アプリケーションを閉じてから再度開き、すぐにログインします。

382

新しいコミュニティログインをテストするMobile SDK アプリケーションでの Communities の使用

例: Facebook 認証できるようにコミュニティを設定する

コミュニティログインを処理するように外部認証プロバイダを設定して、コミュニティへのアクセスを拡張できます。この例では、Facebook を認証フロントエンドとして使用するように前の例を拡張します。この簡単なシナリオでは、認証された Facebook ユーザのコミュニティへの参加を許可できるように外部認証プロバイダを設定します。モバイルアプリケーションにログインできるようにコミュニティがすでに設定されている場合、外部認証を使用するようにモバイルアプリケーションまたは接続アプリケーションを変更する必要はありません。代わりに、Facebook アプリケーション、Salesforce認証プロバイダ、および認証プロバイダApexクラスを定義します。また、コミュニティの設定も若干変更します。

Facebook アプリケーションを作成するFacebook を介したコミュニティログインを有効にするには、まず Facebook アプリケーションを作成します。Facebook アプリケーションは、Salesforce 接続アプリケーションに相当します。接続アプリケーションは、モバイルデバイスのアプリケーションの接続および認証を管理する設定用コンテナです。1. 「Facebook アプリケーションを作成する」に移動します。2. Facebook 開発者アカウントでログインします。Facebook 開発者として登録していない場合は、登録します。3. [アプリケーション] > [新規アプリケーションを作成] に移動します。4. 表示名を「FineApps Community Test」(FineApps コミュニティテスト) に設定します。5. 必要に応じて、名前空間を追加します。Facebook の要件に従って、小文字、ダッシュ、およびアンダース

コアのみで 20 文字以下の名前空間表示ラベルを入力する必要があります。たとえば、「my_fb_goodapps」のようになります。

6. [カテゴリ] で、[公益事業] を選択します。7. 後で使用するためにアプリ ID とアプリのシークレットキーをコピーして保存します。次の URL を使用してアプリケーションにログインできます。https://developers.facebook.com/apps/<App ID>/dashboard/

Salesforce 認証プロバイダを定義するSalesforce で外部認証を有効にするには、認証プロバイダを作成します。Facebook を介した外部認証には、前のステップで作成した Facebook アプリケーションのアプリケーション ID とアプリケーションのシークレットキーが必要です。1. [設定] から、[クイック検索] ボックスに「認証プロバイダ」と入力し、[認証プロバイダ] を選択します。2. [新規] をクリックします。3. 次の表に示すように、認証プロバイダの項目を設定します。

383

例: Facebook 認証できるようにコミュニティを設定するMobile SDK アプリケーションでの Communities の使用

値項目

[Facebook] を選択します。プロバイダタイプ

「FB Community Login」(FB コミュニティログイン) と入力します。

名前

デフォルトを受け入れます。URL 接尾辞

メモ: URL 構文に適合するその他の文字列を入力することもできますが、この例ではデフォルトが最適です。

Facebook アプリケーションのアプリケーション ID を入力します。

コンシューマ鍵

Facebook アプリケーションのアプリのシークレットキーを入力します。

コンシューマの秘密

空白のままにします。カスタムエラー URL

4. [登録ハンドラ] で、[登録ハンドラテンプレートを自動作成] をクリックします。5.

[他のアカウントで登録を実行] で、[検索] をクリックし、管理権限のあるコミュニティメンバーを選択します。

6. [ポータル] は空白のままにします。7. [保存] をクリックします。

Salesforce によって、RegistrationHandler を拡張する新しい Apex クラスが作成されます。このクラス名は、AutocreatedRegHandlerxxxxxx… の形式を取ります。

8. 後で使用するために認証プロバイダ ID をコピーします。9. 新しい認証プロバイダの詳細ページの [クライアント設定] で、後で使用するためにコールバック URL をコ

ピーします。このコールバック URL は、https://login.salesforce.com/services/authcallback/<id>/<Auth.Provider_URL_Suffix>.

の形式を取ります。

Facebook アプリケーションを設定する次に、ログインに Salesforce 認証プロバイダを使用するようにコミュニティを設定します。Salesforce 認証プロバイダを定義したので、Facebook アプリケーションを認証プロバイダにリンクして認証プロトコルを完成させます。Salesforce ログイン URL およびコールバック URL を指定します。この URL には、認証プロバイダ ID と認証プロバイダの URL サフィックスが含まれます。1. Facebook アプリケーションで、[設定] に移動します。

384

Facebook アプリケーションを設定するMobile SDK アプリケーションでの Communities の使用

2. [App Domains (アプリのドメイン)] に、「login.salesforce.com」と入力します。3. [+プラットフォームを追加] をクリックします。4. [Web サイト] を選択します。5. [サイト URL] に、認証プロバイダのコールバック URL を入力します。6. [連絡先メールアドレス] に、有効なメールアドレスを入力します。7. 左パネルで、[Status & Review (ステータス & レビュー)] を [はい] に設定します。この設定により、すべての

Facebook ユーザは Facebook ログインを使用して、コミュニティのユーザアカウントを作成できます。8. [変更を保存] をクリックします。9. [確認] をクリックします。

認証プロバイダの Apex クラスをカスタマイズする認証プロバイダの Apex クラスを使用して、コミュニティに参加できるユーザを制御する条件ロジックを定義します。1. [設定] から、[クイック検索] ボックスに「Apex クラス」と入力し、[Apex クラス] を選択します。2. 認証プロバイダクラスの横にある [編集] をクリックします。デフォルトのクラス名は、

「AutocreatedRegHandlerxxxxxx…」で始まります。3. canCreateUser() メソッドを実装するには、true を返します。

global boolean canCreateUser(Auth.UserData data) {return true;}

この実装により、Facebook を介してログインするすべてのユーザがコミュニティに参加できます。

メモ: 既存のコミュニティメンバーのみがコミュニティにアクセスできるようにするには、検索条件を実装してコミュニティのすべての有効ユーザを識別できるようにします。Facebook パケットの一意のデータ (ユーザ名やメールアドレスなど) の条件に基づいて、コミュニティメンバーのレコードの同様の項目に対してそのデータを検証します。

4. createUser() コードを変更します。a. アカウント名クエリの「Acme」を「FineApps」に置き換えます。b. ユーザ名のサフィックス (「@acmecorp.com」) を「@fineapps.com」に置き換えます。c. プロファイルクエリのプロファイル名 (「カスタマーポータルユーザ」) を「API の有効化」に変更しま

す。

5. updateUser() コードで、ユーザ名 (「myorg.com」) のサフィックスを「@fineapps.com」に置き換えます。

6. [保存] をクリックします。

385

認証プロバイダの Apex クラスをカスタマイズするMobile SDK アプリケーションでの Communities の使用

Salesforce コミュニティを設定する最後のステップでは、ログインに Salesforce 認証プロバイダを使用するようにコミュニティを設定します。1. [設定] から、[クイック検索] ボックスに「コミュニティ」と入力し、[すべてのコミュニティ] を選択しま

す。2. コミュニティ名の横にある [管理] をクリックします。3. [管理] > [ログイン & 登録] をクリックします。4. [ログイン] で、新しい認証プロバイダを選択します。5. [保存] をクリックします。これで完了です。コミュニティログイン URL を使用してモバイルアプリケーションにログインするときに、Facebook を使用したログインを促す追加のボタンが表示されます。そのボタンをクリックして画面の指示に従い、ログインがどのように機能するのかを確認します。ブラウザで外部認証設定をテストするには、(認証プロバイダから) シングルサインオン初期化 URL をカスタマイズします。https://login.salesforce.com/services/auth/sso/orgID/URLsuffix?community=<community_login_url>

次に例を示します。https://login.salesforce.com/services/auth/sso/00Da0000000TPNEAA4/FB_Community_Login?community=https://mobilesdk-developer-edition.server_instance.force.com/fineapps

既存ユーザをリンクする URLを作成するには、sso を link に置き換えます。https://login.salesforce.com/services/auth/link/00Da0000000TPNEAA4/FB_Community_Login?community=https://mobilesdk-developer-edition.server_instance.force.com/fineapps

386

Salesforce コミュニティを設定するMobile SDK アプリケーションでの Communities の使用

第 15 章 Mobile SDK でのマルチユーザのサポート

複数のユーザが同時にログインできるようにするために、Mobile SDKには、ユーザの切り替えの基本的な実装と API が用意されています。

トピック:

• マルチユーザのサポートについて Mobile SDKには、認証されたアカウントから選択できるデフォルトのダイアログボッ

クスが用意されています。アプリケーションでこのダイアログボックスを起動する手段を実装し、ユーザの切り替えフローを開始する API をコールします。

• マルチユーザのサポートの実装

387

マルチユーザのサポートについて

バージョン 2.2 以降、Mobile SDKでは、複数のユーザアカウントから同時にログインできます。これらのアカウントは、同じ組織の異なるユーザか、異なる組織 (本番組織と Sandbox 組織など) の異なるユーザを表します。ユーザがログインすると、サーバに対して再認証することなくアカウント間のシームレスな切り替えを行うことができるようにそのユーザのログイン情報が保存されます。複数のログインをサポートしない場合は、アプリケーションを変更する必要はありません。既存のMobile SDK API は、シングルユーザの場合と同じように機能します。Mobile SDK では、各ユーザアカウントが、認証された他のユーザアカウントに関連していないと想定しています。それに応じて、Mobile SDK では、各アカウントに関連付けられたデータと他のすべてのユーザのデータが分離されます。これにより、アカウント間でデータが混じることを回避できます。データの分離により、アカウントに関連付けられた SharedPreferences ファイル、SmartStore データベース、AccountManager データ、およびその他のフラットファイルが保護されます。

例: ネイティブ Android の場合、RestExplorer サンプルアプリケーションでマルチユーザの切り替えが示されます。ネイティブ iOS の場合、RestAPIExplorer サンプルアプリケーションでマルチユーザの切り替えが示されます。ハイブリッドの場合、次のハイブリッドサンプルアプリケーションでマルチユーザの切り替えが示されます。• SmartStore なし: ContactExplorer

• SmartStore あり: AccountEditor

マルチユーザのサポートの実装

Mobile SDKでは、ネイティブ Android、ネイティブ iOS、およびハイブリッドアプリケーションでマルチユーザのサポートを有効にする API が用意されています。Mobile SDK では基礎となる機能は実装されますが、アプリケーションで次のいずれかの API をコールしない限り、実行時にマルチユーザの切り替えが初期化されません。Android ネイティブ (UserAccountManager クラスメソッド)

public void switchToUser(UserAccount user)

public void switchToNewUser()

iOS ネイティブ (SFUserAccountManager クラスメソッド)- (void)switchToUser:(SFUserAccount *)newCurrentUser

- (void)switchToNewUser

ハイブリッド (JavaScript メソッド)switchToUser

ユーザが別のアカウントに切り替えるようにするには、ユーザインターフェースのボタン、メニュー、またはその他のコントロールから選択画面を起動します。Mobile SDK では、現在認証されているすべてのアカウントをラジオボタンリストに表示する標準のマルチユーザの切り替え画面が用意されています。この画面をカスタ

388

マルチユーザのサポートについてMobile SDK でのマルチユーザのサポート

マイズすることも、デフォルトバージョンをそのまま表示することもできます。ユーザが選択すると、マルチユーザフローを起動する Mobile SDK メソッドをコールします。API の使用を開始する前に、Mobile SDKとアプリケーションの分業を理解しておくことが重要です。次のリストに、Mobile SDK が実行するタスクと、複数のユーザがいる状況でアプリケーションが実行する必要のあるタスクを示します。特に、以下の管理方法を考慮してください。• 転送通知 (アプリケーションでサポートしている場合)

• SmartStore スープ (アプリケーションで SmartStore を使用している場合)

• アカウント管理

転送通知のタスクMobile SDK (すべてのアカウント):

• ログイン時に転送通知を登録する• ログアウト時に転送通知を登録解除する• 転送通知を配信するアプリケーション• 対象ユーザアカウントに応じて通知を識別する• 適切なユーザコンテキストを起動して各通知を表示する

SmartStore のタスクMobile SDK (すべてのアカウント):

• 認証されたユーザアカウントごとに個別の SmartStore データベースを作成する• ユーザの切り替えが発生するたびに適切なバッキングデータベースに切り替えるアプリケーション• ユーザの切り替えまたはログアウトが発生するたびに、キャッシュされたログイン情報 (メモリに保持され

た SmartStore のインスタンスなど) を更新する

アカウント管理のタスクMobile SDK (すべてのアカウント):

• ユーザの切り替えが発生するたびに適切なアカウントログイン情報を読み込むアプリケーション• ユーザの切り替えまたはログアウトが発生するたびに、キャッシュされたログイン情報 (メモリに保持され

た認証済み REST クライアントなど) を更新する

389

マルチユーザのサポートの実装Mobile SDK でのマルチユーザのサポート

Android ネイティブ APIMobile SDK for Android のネイティブクラスは、マルチユーザのサポートの大半の作業を行います。アプリケーションは、いくつかの簡単なコールを行い、メモリにキャッシュされたすべてのデータを処理します。ユーザの切り替えアクティビティをカスタマイズすることもできます。Mobile SDK for Android では、ユーザの切り替えをサポートするために、com.salesforce.androidsdk.accounts、com.salesforce.androidsdk.ui、およびcom.salesforce.androidsdk.util パッケージのネイティブクラスを定義します。com.salesforce.androidsdk.accounts パッケージには、次のクラスがあります。• UserAccount

• UserAccountManager

com.salesforce.androidsdk.uiパッケージには、AccountSwitcherActivityクラスがあります。このクラスを拡張して、アカウントの切り替えアクティビティを高度にカスタマイズできます。com.salesforce.androidsdk.utilパッケージには、UserSwitchReceiver抽象クラスがあります。アプリケーションでトークン以外のデータをキャッシュする場合、このクラスを実装する必要があります。次セクションでは、これらのクラスについて簡単に説明します。完全な API リファレンスドキュメントについては、http://forcedotcom.github.io/SalesforceMobileSDK-Android/index.html を参照してください。

マルチユーザフローネイティブ Android アプリケーションの場合、UserAccountManager.switchToUser() Mobile SDKメソッドがマルチユーザフローを起動します。アプリケーションでこのメソッドがコールされると、Mobile SDK コアがすべてのパスで実行フローを処理します。次のダイアグラムに、このフローを示します。

390

Android ネイティブ APIMobile SDK でのマルチユーザのサポート

このセクションの内容:

UserAccount クラスUserAccountクラスは、現在認証されている単一のユーザアカウントを表します。このクラスは、ユーザアカウントを一意に識別するために使用できるデータをカプセル化します。UserAccountManager クラスUserAccountManagerクラスは、認証されたアカウントへのアクセス、新しいアカウントの追加、既存のアカウントのログアウト、既存のアカウント間の切り替えを行うメソッドを提供します。AccountSwitcherActivity クラスAccountSwitcherActivityクラスを使用または拡張して、ユーザの切り替えのインターフェースを表示します。UserSwitchReceiver クラスネイティブ Android アプリケーションがトークン以外のデータをキャッシュする場合、UserSwitchReceiver

抽象クラスを実装して、ユーザの切り替えイベントの通知を受信します。

UserAccount クラスUserAccount クラスは、現在認証されている単一のユーザアカウントを表します。このクラスは、ユーザアカウントを一意に識別するために使用できるデータをカプセル化します。

391

Android ネイティブ APIMobile SDK でのマルチユーザのサポート

コンストラクタJSON オブジェクトまたはバンドルから直接 UserAccount オブジェクトを作成できます。

説明コンストラクタ

指定した値を使用して UserAccountオブジェクトを作成します。

public UserAccount(String authToken,String refreshToken,String loginServer,String idUrl,String instanceServer,String orgId,String userId,String username,String accountName,String clientId,String communityId,String communityUrl)

JSON 文字列から UserAccountオブジェクトを作成します。

public UserAccount(JSONObject object)

Android アプリケーションバンドルから UserAccount

オブジェクトを作成します。public UserAccount(Bundle bundle)

メソッド

説明メソッド

このユーザアカウントの組織レベルのストレージパス(アプリケーションデータの上位レベルのディレクト

public String getOrgLevelStoragePath()

リに対する相対パス) を返します。上位レベルのディレクトリは files などになります。出力の形式は、/{orgID}/ になります。これは、同じ組織の複数のユーザで共有できるデータのストレージパスです。

このユーザアカウントのユーザレベルのストレージパス (アプリケーションデータの上位レベルのディレク

public String getUserLevelStoragePath()

トリに対する相対パス) を返します。上位レベルのディレクトリは files などになります。出力の形式は、/{orgID}/{userID}/ になります。これは、組織の特定のユーザに固有のデータのストレージパスですが、そのユーザがメンバーであるその組織内のすべてのコミュニティで共有されるデータのストレージパスでもあります。

392

Android ネイティブ APIMobile SDK でのマルチユーザのサポート

説明メソッド

このユーザアカウントのコミュニティレベルのストレージパス (アプリケーションデータの上位レベルの

public StringgetCommunityLevelStoragePath(StringcommunityId) ディレクトリに対する相対パス) を返します。上位レ

ベルのディレクトリは files などになります。出力の形式は、/{orgID}/{userID}/{communityID}/

になります。communityID が null の場合、出力は/{orgID}/{userID}/internal/ のようになります。これは、特定のコミュニティの特定のユーザに固有のデータのストレージパスです。

このユーザアカウントの一意のサフィックスを返します。このサフィックスをファイルに追加して、組織レ

public String getOrgLevelFilenameSuffix()

ベルでこのアカウントを一意に識別できます。出力の形式は、_{orgID}になります。これは、同じ組織の複数のユーザで共有できるデータのサフィックスです。

このユーザアカウントの一意のサフィックスを返します。このサフィックスをファイルに追加して、ユーザ

public String getUserLevelFilenameSuffix()

レベルでこのアカウントを一意に識別できます。出力の形式は、_{orgID}_{userID} になります。これは、組織の特定のユーザに固有のデータのサフィックスですが、そのユーザがメンバーであるその組織内のすべてのコミュニティで共有されるデータのサフィックスでもあります。

このユーザアカウントの一意のサフィックスを返します。このサフィックスをファイルに追加して、コミュ

public StringgetCommunityLevelFilenameSuffix(StringcommunityId) ニティレベルでこのアカウントを一意に識別できま

す。出力の形式は、_{orgID}_{userID}_{communityID}になります。communityID が null の場合、出力は_{orgID}_{userID}_internalのようになります。これは、特定のコミュニティの特定のユーザに固有のデータのサフィックスです。

UserAccountManager クラスUserAccountManager クラスは、認証されたアカウントへのアクセス、新しいアカウントの追加、既存のアカウントのログアウト、既存のアカウント間の切り替えを行うメソッドを提供します。UserAccountManager のインスタンスは直接作成しません。代わりに、次のコールを使用してインスタンスを取得します。SalesforceSDKManager.getInstance().getUserAccountManager();

393

Android ネイティブ APIMobile SDK でのマルチユーザのサポート

メソッド

説明メソッド

現在有効なユーザアカウントを返します。public UserAccount getCurrentUser()

認証されたユーザアカウントのリストを返します。public List<UserAccount>getAuthenticatedUsers()

指定されたユーザアカウントがすでに認証されているかどうかを確認します。

public booleandoesUserAccountExist(UserAccount account)

指定されたユーザアカウントにアプリケーションコンテキストを切り替えます。指定されたユーザアカウン

public void switchToUser(UserAccount user)

トが無効または null の場合、このメソッドはログインフローを起動します。

新しいユーザがログインするためのログインフローを起動します。

public void switchToNewUser()

指定されたユーザをアプリケーションからログアウトさせて、そのユーザのログイン情報を消去します。

public void signoutUser(UserAccountuserAccount, Activity frontActivity)

AccountSwitcherActivity クラスAccountSwitcherActivity クラスを使用または拡張して、ユーザの切り替えのインターフェースを表示します。AccountSwitcherActivityクラスは、マルチユーザログインを処理する画面を提供します。この画面では、既存のユーザアカウントのリストが表示され、ユーザは既存のアカウントを切り替えたり、新しいアカウントにサインインしたりできます。マルチユーザログインを有効にするには、次のコードを使用してアプリケーションの任意の場所からアクティビティを起動します。final Intent i = new Intent(this, SalesforceSDKManager.getInstance().

getAccountSwitcherActivityClass());i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);this.startActivity(i);

たとえば、ユーザインターフェースの「ユーザの切り替え」ボタンからこのアクティビティを起動できます。例については、SampleApps/RestExplorerを参照してください。必要に応じて、XML を介して AccountSwitcherActivity をカスタマイズおよびスタイル設定できます。さらに詳細に制御するために、AccountSwitcherActivity を拡張したり、独自のカスタムサブクラスに置き換えたりできます。デフォルトクラスを置き換えるには、SalesforceSDKManager.setAccountSwitcherActivityClass() をコールします。置き換わるアクティビティクラス (AccountSwitcherActivity.class など) のクラスファイルに参照を渡します。

394

Android ネイティブ APIMobile SDK でのマルチユーザのサポート

UserSwitchReceiver クラスネイティブ Android アプリケーションがトークン以外のデータをキャッシュする場合、UserSwitchReceiver

抽象クラスを実装して、ユーザの切り替えイベントの通知を受信します。ユーザの切り替えが発生するたびに、Mobile SDKはインテントをブロードキャストします。インテントアクションは、次のように UserAccountManager クラスで宣言されます。public static final String USER_SWITCH_INTENT_ACTION =

"com.salesforce.USERSWITCHED";

このブロードキャストイベントにより、キャッシュされたリソースをアプリケーションで適切に更新して、ユーザの切り替えに対応できます。アプリケーションがこのイベントをリスンできるように、Mobile SDKには、UserSwitchReceiver 抽象クラスが用意されています。このクラスは、次の Salesforce アクティビティクラスで実装されます。• SalesforceActivity

• SalesforceListActivity

• SalesforceExpandableListActivity

メインアクティビティでいずれかのSalesforceアクティビティクラスを拡張する場合、UserSwitchReceiver

を実装する必要はありません。メモリにトークンのみをキャッシュしている場合、何もする必要はありません。Mobile SDKが自動的にトークンを更新します。トークン以外のユーザデータをキャッシュしている場合、カスタム更新アクションでアクティビティのrefreshIfUserSwitched() メソッドを上書きします。

メインアクティビティでいずれかのSalesforceアクティビティクラスを拡張しない場合、UserSwitchReceiver

を実装して、ユーザの切り替え時にキャッシュされたデータを処理します。ブロードキャストレシーバを設定する手順は、次のとおりです。1. UserSwitchReceiver のサブクラスを実装します。2. アクティビティの onCreate() メソッドでサブクラスをレシーバとして登録します。3. アクティビティの onDestroy() メソッドでレシーバを登録解除します。例については、RestExplorer サンプルアプリケーションの ExplorerActivity クラスを参照してください。

アプリケーションがハイブリッドアプリケーションの場合、作業は必要ありません。SalesforceDroidGapActivity クラスは、ユーザの切り替えの発生時に必要に応じてキャッシュを更新します。

メソッド1 つのメソッドで実装が必要になります。

説明メソッド名

このメソッドを実装して、ユーザの切り替えの発生時にキャッシュされたユーザデータ (トークン以外) を処理します。

protected abstract void onUserSwitch();

395

Android ネイティブ APIMobile SDK でのマルチユーザのサポート

iOS ネイティブ APIMobile SDK for iOS のネイティブクラスは、マルチユーザのサポートの大半の作業を行います。アプリケーションは、いくつかの簡単なコールを行い、メモリにキャッシュされたすべてのデータを処理します。ユーザの切り替えアクティビティをカスタマイズすることもできます。Mobile SDK for iOS では、ユーザの切り替えをサポートするために、SalesforceSDKCoreライブラリの Security

フォルダのネイティブクラスを定義します。クラスには、以下が含まれます。• SFUserAccount

• SFUserAccountManager

次セクションでは、これらのクラスについて簡単に説明します。完全な API リファレンスドキュメントについては、『SalesforceSDKCore Reference』を参照してください。

このセクションの内容:

SFUserAccount クラスSFUserAccountクラスは、現在認証されている単一のユーザアカウントを表します。このクラスは、ユーザアカウントを一意に識別するために使用できるデータをカプセル化します。SFUserAccountManager クラスSFUserAccountManager クラスは、認証されたアカウントへのアクセス、新しいアカウントの追加、アカウントのログアウト、アカウント間の切り替えを行うメソッドを提供します。

SFUserAccount クラスSFUserAccountクラスは、現在認証されている単一のユーザアカウントを表します。このクラスは、ユーザアカウントを一意に識別するために使用できるデータをカプセル化します。

プロパティJSON オブジェクトまたはバンドルから直接 SFUserAccount オブジェクトを作成できます。

説明プロパティ

このユーザのアクセス範囲。@property (nonatomic, copy)NSSet *accessScopes

このユーザに関連付けられたログイン情報。@property (nonatomic, strong)SFOAuthCredentials *credentials;

このユーザに関連付けられた ID データ。@property (nonatomic, strong)SFIdentityData *idData;

サーバ側の API を呼び出するために使用できる URL。この URL では、現在のコミュニティが考慮されます(使用可能な場合)。

@property (nonatomic, copy, readonly)NSURL *apiUrl;

396

iOS ネイティブ APIMobile SDK でのマルチユーザのサポート

説明プロパティ

ユーザのメールアドレス。@property (nonatomic, copy)NSString *email;

ユーザの組織の名前。@property (nonatomic, copy)NSString *organizationName;

ユーザの名と姓。@property (nonatomic, copy)NSString *fullName;

ユーザのユーザ名。@property (nonatomic, copy)NSString *userName;

ユーザの写真 (通常、ユーザのサムネイル)。このクラスのコンシューマは、写真を使用するために少なくと

@property (nonatomic, strong)UIImage *photo;

も 1 回はこのプロパティを設定する必要があります。このクラスは、サーバから写真を取得しません。写真はローカルで保存および取得されます。

このユーザに関連付けられたアクセス制限。@property (nonatomic)SFUserAccountAccessRestrictionaccessRestrictions;

現在のコミュニティ ID (ユーザがコミュニティにログインしている場合)。コミュニティにログインしていない場合、このプロパティは nil になります。

@property (nonatomic, copy)NSString *communityId;

ユーザにアクセストークンがあり、有効なセッションだと想定される場合、YES を返します。

@property (nonatomic, readonly, getter =isSessionValid)BOOL sessionValid;

ユーザのカスタムデータ。このデータは逐次化できるため、customData に含まれるオブジェクトはNSCoding プロトコルに準拠する必要があります。

@property (nonatomic, copy)NSDictionary *customData;

グローバル関数

説明関数名

特定の範囲でこのユーザアカウントを一意に識別するキーを返します。scope を

NSString *SFKeyForUserAndScope(SFUserAccount *user, SFUserAccountScopescope); SFUserAccountScopeGlobal に設定すると、ユー

ザアカウントに関係なく同じキーが返されます。

397

iOS ネイティブ APIMobile SDK でのマルチユーザのサポート

SFUserAccountManager クラスSFUserAccountManagerクラスは、認証されたアカウントへのアクセス、新しいアカウントの追加、アカウントのログアウト、アカウント間の切り替えを行うメソッドを提供します。シングルトン SFUserAccountManager インスタンスにアクセスするには、次のメッセージを送信します。[SFUserAccountManager sharedInstance]

プロパティ

説明プロパティ

現在のユーザアカウント。 ユーザがログインしていない場合、このプロパティは nil になる可能性があります。

@property (nonatomic, strong) SFUserAccount*currentUser

現在のユーザの ID を取得する便利なプロパティ。このプロパティは、currentUser.credentials.userId の別名です。

@property (nonatomic, readonly) NSString*currentUserId

現在のユーザのコミュニティ ID を取得する便利なプロパティ。このプロパティは、currentUser.communityId の別名です。

@property (nonatomic, readonly) NSString*currentCommunityId

アプリケーションのすべての SFUserAccountインスタンスの NSArray。

@property (nonatomic, readonly) NSArray*allUserAccounts

すべてのユーザ ID を含む配列を返します。@property (nonatomic, readonly) NSArray*allUserIds

最後の有効なユーザ ID。activeUserId によって指定されたユーザがアカウントリストから削除されてい

@property (nonatomic, copy) NSString*activeUserId

ると、このユーザは現在のユーザとは一時的に異なる場合があります。

ログインに使用されるホスト。@property (nonatomic, strong) NSString*loginHost

ログインプロセスが失敗した場合にログインプロセスを再起動するかどうかを制御するフラグ。デフォルト値は YES です。

@property (nonatomic, assign) BOOLretryLoginAfterFailure

OAuth ログインプロセスに使用される OAuth コールバック URL。このプロパティは、アプリケーションによっ

@property (nonatomic, copy) NSString*oauthCompletionUrl

てカスタマイズされている場合があります。デフォルトでは、プロパティの値は、メインバンドルのSFDCOAuthRedirectUriプロパティからコピーされます。デフォルト値は、

398

iOS ネイティブ APIMobile SDK でのマルチユーザのサポート

説明プロパティ

@"testsfdc:///mobilesdk/detect/oauth/done"

です。

アプリケーションに関連付けられた OAuth 範囲。@property (nonatomic, copy) NSSet *scopes

メソッド

説明メソッド

指定されたユーザアカウントの.plist ファイルのパスを返します。

- (NSString*)userAccountPlistFileForUser:(SFUserAccount*)user

このユーザアカウントマネージャに代理を追加します。

- (void)addDelegate:(id<SFUserAccountManagerDelegate>)delegate

このユーザアカウントマネージャから代理を削除します。

- (void)removeDelegate:(id<SFUserAccountManagerDelegate>)delegate

アプリケーション設定でアプリケーションレベルのログインホストをこの値に設定します。

- (SFLoginHostUpdateResult*)updateLoginHost

すべてのアカウントを読み込みます。

- (BOOL)loadAccounts:(NSError**)error

すべてのアカウントを保存します。

- (BOOL)saveAccounts:(NSError**)error

すべてのアカウント情報を自分自身で設定する場合に空のユー

- (SFUserAccount*)createUserAccount

ザアカウントを作成するために使用できます。それ以外の場合は、必要に応じて[SFAuthenticationManagerloginWithCompletion:failure:]

を使用し、アカウントを自動的に作成します。

特定のユーザ ID に関連付けられたユーザアカウントを返します。

- (SFUserAccount*)userAccountForUserId:(NSString*)userId

特定の組織にアクセスできるすべてのアカウントを返します。

- (NSArray*)accountsForOrgId:(NSString*)orgId

399

iOS ネイティブ APIMobile SDK でのマルチユーザのサポート

説明メソッド

特定のインスタンス URL に一致するすべてのアカウントを返します。

- (NSArray *)accountsForInstanceURL:(NSString *)instanceURL

ユーザアカウントを追加します。

- (void)addAccount:(SFUserAccount*)acct

特定のユーザ ID に関連付けられたユーザアカウントを削除します。

- (BOOL)deleteAccountForUserId:(NSString*)userIderror:(NSError **)error

メモリ内のアカウントの状態をクリアします (ただし、ディス

- (void)clearAllAccountState

クの内容は何も変更されません)。

指定されたログイン情報を現在のユーザに適用します。ユーザ

- (void)applyCredentials:(SFOAuthCredentials*)credentials が存在しない場合、ユーザが作

成されます。

そのユーザの Sandbox の外部からアクセスできる

- (void)applyCustomDataToCurrentUser:(NSDictionary*)customData

SFUserAccount にカスタムデータを適用します。このデータは、アプリケーションの起動ごとに変わることはありません。このデータは逐次化されるため、customDataに含まれるオブジェクトが NSCodingプロトコルに準拠していることを確認してください。

重要: このメソッドは、機密情報以外にのみに使用します。

現在のユーザから新しいユーザコンテキストに切り替えます。

- (void)switchToNewUser

現在のユーザを指定されたユーザアカウントに切り替えます。

- (void)switchToUser:(SFUserAccount *)newCurrentUser

現在のユーザに何らかの変更があったことを

- (void)userChanged:(SFUserAccountChange)change

400

iOS ネイティブ APIMobile SDK でのマルチユーザのサポート

説明メソッド

SFUserAccountManager オブジェクトに通知します。

ハイブリッド APIハイブリッドアプリケーションは、Mobile SDK JavaScript API を介して、マルチユーザのサポートを有効にできます。これらの API は、SFAccountManagerPlugin Cordova ベースのモジュールにあります。

SFAccountManagerPlugin メソッドこれらのメソッドをコールする前に、sfaccountmanagerプラグインを読み込む必要があります。たとえば、次のような場合です。cordova.require("com.salesforce.plugin.sfaccountmanager").logout();

説明メソッド名

すでにログインしているユーザのリストを返します。getUsers

現在の有効なユーザを返します。getCurrentUser

ユーザが渡された場合は指定されたユーザをログアウトさせます。引数を指定しないでコールした場合は、現在のユーザをログアウトさせます。

logout

指定したユーザにアプリケーションコンテキストを切り替えます。ユーザが指定されていない場合は、アカウントの切り替え画面を起動します。

switchToUser

ハイブリッドアプリケーションでは、マルチユーザの切り替えのブロードキャストイベントのレシーバを実装する必要はありません。このハンドラは、SalesforceDroidGapActivity クラスで実装されます。

401

ハイブリッド APIMobile SDK でのマルチユーザのサポート

第 16 章 以前のリリースからの移行

Salesforce Mobile SDK4.2を使用して作成されたアプリケーションをアップグレードする場合は、次の手順に従ってアプリケーションをバージョン 4.3 に更新します。

トピック:

• Android アプリケーションを 4.2 から4.3 に移行する

Salesforce Mobile SDK4.2より前のバージョンを使用して作成されたアプリケーションをアップグレードする場合は、「以前のリリースからの移行」を参照してアップグレードを開始します。• iOS アプリケーショ

ンを 4.2 から 4.3 に移行する

• ハイブリッドアプリケーションを 4.2から 4.3 に移行する

• 以前のリリースからの移行

402

Android アプリケーションを 4.2 から 4.3 に移行する

ネイティブ Android アプリケーションをアップグレードするには、forcedroid を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。

iOS アプリケーションを 4.2 から 4.3 に移行する

ネイティブ iOS アプリケーションをアップグレードするには、forceios を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。または、CocoaPodsのみを使用してアップグレードすることをお勧めします。「CocoaPods と Mobile SDK の使用」を参照してください。CocoaPods を使用して SmartStore アプリケーションをアップグレードする場合は、「SalesforceSDKManager および SmartStoreSDKManager クラス」の説明に従って AppDelegate クラスを更新してください。

ハイブリッドアプリケーションを 4.2 から 4.3 に移行する• Mobile SDK 4.3 の Cordova サポートは次のバージョンに更新されています。

– iOS: Cordova 4.2.0 にアップグレード– Android: 変更なし — Cordova 5.0.0 のままcordova platform add コマンドを使用するときは、必ずこれらのバージョンを指定してください。

• ハイブリッドアプリケーションをアップグレードするには、forceios または forcedroid を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。または、Cordova コマンドラインを使用して Salesforce Cordova プラグインをアップグレードすることもできます。削除してから、プラグインを再度追加します。$ cd MyCordovaAppDir$ cordova plugin rm com.salesforce$ cordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugin$ cordova prepare

以前のリリースからの移行

以前のリリースよりも古いバージョンから移行するには、現在のバージョンから始めて、介在するリリースごとにコードのアップグレード手順を実行します。

Android アプリケーションを 4.1 から 4.2 に移行するネイティブ Android アプリケーションをアップグレードするには、forcedroid を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。

403

Android アプリケーションを 4.2 から 4.3 に移行する以前のリリースからの移行

iOS アプリケーションを 4.1 から 4.2 に移行するネイティブ iOS アプリケーションをアップグレードするには、forceios を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。または、CocoaPodsのみを使用してアップグレードすることをお勧めします。「CocoaPods と Mobile SDK の使用」を参照してください。CocoaPods を使用して SmartStore アプリケーションをアップグレードする場合は、「SalesforceSDKManager および SmartStoreSDKManager クラス」の説明に従って AppDelegate クラスを更新してください。

ハイブリッドアプリケーションを 4.1 から 4.2 に移行するハイブリッドアプリケーションをアップグレードするには、forceios または forcedroid を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。または、Cordova コマンドラインを使用して Salesforce Cordova プラグインをアップグレードすることもできます。削除してから、プラグインを再度追加します。$ cd MyCordovaAppDir$ cordova plugin rm com.salesforce$ cordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugin$ cordova prepare

Android アプリケーションを 4.0 から 4.1 に移行するネイティブ Android アプリケーションをアップグレードするには、forcedroid を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。

iOS アプリケーションを 4.0 から 4.1 に移行するネイティブ iOS アプリケーションをアップグレードするには、forceios を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。または、CocoaPodsのみを使用してアップグレードすることをお勧めします。CocoaPodsを使用してSmartStoreアプリケーションをアップグレードする場合は、「SalesforceSDKManager および SmartStoreSDKManager クラス」の説明に従って AppDelegate クラスを更新してください。

関連トピック:

CocoaPods と Mobile SDK の使用

ハイブリッドアプリケーションを 4.0 から 4.1 に移行するハイブリッドアプリケーションをアップグレードするには、forceios または forcedroid を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。ま

404

iOS アプリケーションを 4.1 から 4.2 に移行する以前のリリースからの移行

たは、Cordova コマンドラインを使用して Salesforce Cordova プラグインをアップグレードすることもできます。削除してから、プラグインを再度追加します。$ cd MyCordovaAppDir$ cordova plugin rm com.salesforce$ cordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugin$ cordova prepare

Android アプリケーションを 3.3 から 4.0 に移行するネイティブ Android アプリケーションをアップグレードするには、forcedroid を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。

iOS アプリケーションを 3.3 から 4.0 に移行するネイティブ iOS アプリケーションをアップグレードするには、forceios を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。または、CocoaPodsのみを使用してアップグレードすることをお勧めします。CocoaPodsを使用してSmartStoreアプリケーションをアップグレードする場合は、「SalesforceSDKManager および SmartStoreSDKManager クラス」の説明に従って AppDelegate クラスを更新してください。

関連トピック:

CocoaPods と Mobile SDK の使用

ハイブリッドアプリケーションを 3.3 から 4.0 に移行するハイブリッドアプリケーションをアップグレードするには、forceios または forcedroid を使用してアプリケーションを作成してからアプリケーションのアイテムを新しいテンプレートに移行することを強くお勧めします。または、Cordova コマンドラインを使用して Salesforce Cordova プラグインをアップグレードすることもできます。削除してから、プラグインを再度追加します。$ cd MyCordovaAppDir$ cordova plugin rm com.salesforce$ cordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugin$ cordova prepare

ハイブリッドアプリケーションを 3.2 から 3.3 に移行するネイティブおよびハイブリッド iOS アプリケーションをアップグレードする最も簡単な方法は、最新バージョンの forceios で新しいアプリケーションを作成することです。新しいアプリケーションの準備が整ったら、アプリケーションのコードを新しいテンプレートに移行します。ハイブリッドアプリケーションの場合にこれを実行すると、アプリケーションの Cordova 基盤が現在の Mobile SDK Cordova プラグインと一致します。Mobile SDK 4.2 から Mobile SDK 4.3 にアップグレードするために、既存の Web アプリケーションコードを変更する必要はありません。行う操作は、Salesforce Cordova プラグインのアップグレードだけです。Mobile SDK 4.3では、

405

Android アプリケーションを 3.3 から 4.0 に移行する以前のリリースからの移行

Cordova (iOS の場合は 4.2.0、Android の場合は 5.0.0)以降がサポートされ、Cordova 3.7 でも動作することが予想されます。Salesforce Cordova プラグインをアップグレードするには、次に示すように Cordova コマンドラインツールを使用して削除してから、プラグインを再度追加します。

例:

$ cd <your_Cordova_app_folder>$ cordova plugin rm com.salesforce$ cordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugin$ cordova prepare

Android ネイティブアプリケーションを 3.2 から 3.3 に移行するAndroid ネイティブアプリケーションを Salesforce Mobile SDK 3.2 からバージョン 3.3 にアップグレードするには、次の手順を実行します。1. Eclipse で Mobile SDK プロジェクトワークスペースを開きます。2. 既存の Cordova プロジェクトを Mobile SDK 3.3 Cordova プロジェクトに置き換えます。3. 既存の SalesforceSDK プロジェクトを新しい SalesforceSDK プロジェクトに置き換えます。4. アプリケーションで SmartStore を使用する場合は、既存の SmartStore プロジェクトを新しい SmartStore プロ

ジェクトに置き換えます。5. アプリケーションでSmartSyncを使用する場合は、既存のSmartSyncプロジェクトを新しいSmartSyncプロジェ

クトに置き換えます。6. プロジェクトエクスプローラで、プロジェクトを右クリックして [Properties (プロパティ)] を選択します。7. 左パネルで、[Android] を選択します。8. [Library (ライブラリ)] セクションで、既存の SalesforceSDK エントリをワークスペースの新しい SalesforceSDK プ

ロジェクトに置き換えます。9. アプリケーションで SmartStore を使用する場合は、SmartStore プロジェクトでステップ 8 を繰り返します。10. アプリケーションで SmartSync を使用する場合は、SmartSync プロジェクトでステップ 8 を繰り返します。

iOS ネイティブアプリケーションを 3.2 から 3.3 に移行するMobile SDK 3.3 への移行は、わずかな作業で実行できます。以前のリリースと同様、iOS のサポートされている最小バージョンは 8 で、Xcode のサポートされている最小バージョンは 7 です。iOS または Xcode のこれより前のバージョンの後方互換性は保証されません。Mobile SDK 3.2 アプリケーションをMobile SDK 3.3 にアップグレードするには、「Mobile SDK ライブラリパッケージを更新する」の手順を実行します。

Mobile SDK ライブラリパッケージを更新するネイティブおよびハイブリッド iOS アプリケーションをアップグレードする最も簡単な方法は、最新バージョンの forceios で新しいアプリケーションを作成することです。新しいアプリケーションの準備が整ったら、ア

406

Android ネイティブアプリケーションを 3.2 から 3.3 に移行する

以前のリリースからの移行

プリケーションのコードを新しいテンプレートに移行します。代わりに、既存のアプリケーションで Mobile

SDK アイテムを手動で更新する場合、次の手順を実行します。CocoaPods でアプリケーションの Mobile SDK 連動関係を管理する場合、次の手順を実行する必要はありません。Mobile SDKライブラリパッケージを更新するには、アプリケーションの Xcode プロジェクトの既存の Dependencies

フォルダを削除してから、再作成した Dependencies フォルダに新しいライブラリを追加します。1. SalesforceMobileSDK-iOS-Distribution リポジトリ (https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Distribution) か

ら次のバイナリパッケージをダウンロードします。• SalesforceRestAPI-Release.zip

• SalesforceNetwork-Release.zip

• SalesforceOAuth-Release.zip

• SalesforceSDKCore-Release.zip

• SalesforceSecurity-Release.zip

• SmartSync-Release.zip

• SalesforceSDKCommon-Release.zip

2. また、配布リポジトリの ThirdParty フォルダリンクから次のフォルダもダウンロードします。• SalesforceCommonUtils

• sqlcipher

3. Xcode で Mobile SDK プロジェクトを開きます。4. プロジェクトナビゲータで、Dependencies フォルダを見つけます。5. Ctrl キーを押しながらフォルダをクリックします。[Delete (削除)] を選択し、[Move to Trash (ゴミ箱に移動)]

を選択します。6. Xcode プロジェクトで、アプリケーションフォルダの下に Dependencies フォルダを再作成します。7. Dependencies フォルダに、ステップ 1 の新しいパッケージを解凍し、ステップ 2 のフォルダをコピーします。8. プロジェクトナビゲータで、Ctrl キーを押しながらアプリケーションフォルダをクリックし、[Add Files to

"<App Name>"... (「<アプリケーション名>」にファイルを追加...)] を選択します。9. Dependencies フォルダを選択し、追加したフォルダで [Create groups (グループを作成)] が選択されているこ

とを確認します。10. [追加] をクリックします。

Android ネイティブアプリケーションを 3.1 から 3.2 に移行するAndroid ネイティブアプリケーションを Salesforce Mobile SDK 3.1 からバージョン 3.2 にアップグレードするには、次の手順を実行します。1. Eclipse で Mobile SDK プロジェクトワークスペースを開きます。2. 既存の Cordova プロジェクトを Mobile SDK 3.2 Cordova プロジェクトに置き換えます。3. 既存の SalesforceSDK プロジェクトを新しい SalesforceSDK プロジェクトに置き換えます。4. アプリケーションで SmartStore を使用する場合は、既存の SmartStore プロジェクトを新しい SmartStore プロ

ジェクトに置き換えます。

407

Android ネイティブアプリケーションを 3.1 から 3.2 に移行する

以前のリリースからの移行

5. アプリケーションでSmartSyncを使用する場合は、既存のSmartSyncプロジェクトを新しいSmartSyncプロジェクトに置き換えます。

6. プロジェクトエクスプローラで、プロジェクトを右クリックして [Properties (プロパティ)] を選択します。7. 左パネルで、[Android] を選択します。8. [Library (ライブラリ)] セクションで、既存の SalesforceSDK エントリをワークスペースの新しい SalesforceSDK プ

ロジェクトに置き換えます。9. アプリケーションで SmartStore を使用する場合は、SmartStore プロジェクトでステップ 8 を繰り返します。10. アプリケーションで SmartSync を使用する場合は、SmartSync プロジェクトでステップ 8 を繰り返します。

ハイブリッドアプリケーションを 3.1 から 3.2 に移行するネイティブおよびハイブリッド iOS アプリケーションをアップグレードする最も簡単な方法は、最新バージョンの forceios で新しいアプリケーションを作成することです。新しいアプリケーションの準備が整ったら、アプリケーションのコードを新しいテンプレートに移行します。ハイブリッドアプリケーションの場合にこれを実行すると、アプリケーションの Cordova 基盤が現在の Mobile SDK Cordova プラグインと一致します。Mobile SDK 3.1 から Mobile SDK 3.2 にアップグレードするために、既存の Web アプリケーションコードを変更する必要はありません。行う操作は、Salesforce Cordova プラグインのアップグレードだけです。Mobile SDK 3.2 では、Cordova (iOS の場合は 4.2.0、Android の場合は 5.0.0)以降がサポートされ、Cordova 3.7 でも動作することが予想されます。Salesforce Cordova プラグインをアップグレードするには、次に示すように Cordova コマンドラインツールを使用して削除してから、プラグインを再度追加します。

例:

$ cd <your_Cordova_app_folder>$ cordova plugin rm com.salesforce$ cordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugin$ cordova prepare

iOS ネイティブアプリケーションを 3.1 から 3.2 に移行するMobile SDK 3.2 への移行は、わずかな作業で実行できます。以前のリリースと同様、iOS のサポートされている最小バージョンは 7.0 で、Xcode のサポートされている最小バージョンは 6.0 です。iOS または Xcode のこれより前のバージョンの後方互換性は保証されません。Mobile SDK 3.2 では、MKNetworkKit および SalesforceNetworkSDK ネットワーキングライブラリが SalesforceNetwork ライブラリに置き換えられました。アプリケーションで MKNetworkKit API を直接コールすると、それらのコールはSalesforceNetwork ライブラリの同等の API へのコールに置き換えられます。Mobile SDK 3.1 アプリケーションをMobile SDK 3.2 にアップグレードするには、「Mobile SDK ライブラリパッケージを更新する」の手順を実行します。

408

ハイブリッドアプリケーションを 3.1 から 3.2 に移行する

以前のリリースからの移行

Mobile SDK ライブラリパッケージを更新するネイティブおよびハイブリッド iOS アプリケーションをアップグレードする最も簡単な方法は、最新バージョンの forceios で新しいアプリケーションを作成することです。新しいアプリケーションの準備が整ったら、アプリケーションのコードを新しいテンプレートに移行します。代わりに、既存のアプリケーションで Mobile

SDK アイテムを手動で更新する場合、次の手順を実行します。CocoaPods でアプリケーションの Mobile SDK 連動関係を管理する場合、次の手順を実行する必要はありません。Mobile SDKライブラリパッケージを更新するには、アプリケーションの Xcode プロジェクトの既存の Dependencies

フォルダを削除してから、再作成した Dependencies フォルダに新しいライブラリを追加します。1. SalesforceMobileSDK-iOS-Distribution リポジトリ (https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Distribution) か

ら次のバイナリパッケージをダウンロードします。• SalesforceRestAPI-Release.zip

• SalesforceNetwork-Release.zip

• SalesforceOAuth-Release.zip

• SalesforceSDKCore-Release.zip

• SalesforceSecurity-Release.zip

• SmartSync-Release.zip

• SalesforceSDKCommon-Release.zip

2. また、配布リポジトリの ThirdParty フォルダリンクから次のフォルダもダウンロードします。• SalesforceCommonUtils

• openssl

• sqlcipher

3. Xcode で Mobile SDK プロジェクトを開きます。4. プロジェクトナビゲータで、Dependencies フォルダを見つけます。5. Ctrl キーを押しながらフォルダをクリックします。[Delete (削除)] を選択し、[Move to Trash (ゴミ箱に移動)]

を選択します。6. Xcode プロジェクトで、アプリケーションフォルダの下に Dependencies フォルダを再作成します。7. Dependencies フォルダに、ステップ 1 の新しいパッケージを解凍し、ステップ 2 のフォルダをコピーします。8. プロジェクトナビゲータで、Ctrl キーを押しながらアプリケーションフォルダをクリックし、[Add Files to

"<App Name>"... (「<アプリケーション名>」にファイルを追加...)] を選択します。9. Dependencies フォルダを選択し、追加したフォルダで [Create groups (グループを作成)] が選択されているこ

とを確認します。10. [Add (追加)] をクリックします。

ハイブリッドアプリケーションを 3.0 から 3.1 に移行する既存の Mobile SDK 3.0 ハイブリッドアプリケーションは、Mobile SDK 3.1 でコードを変更しなくても動作します。行う操作は、Salesforce Cordova プラグインのアップグレードだけです。Mobile SDK 3.1 では、Cordova 3.5 以降がサポートされ、Cordova 3.6.3 までテスト済みで、Cordova 3.7 でも動作することが予想されます。

409

ハイブリッドアプリケーションを 3.0 から 3.1 に移行する

以前のリリースからの移行

Salesforce Cordova プラグインをアップグレードするには、次に示すように Cordova コマンドラインツールを使用して削除してから、プラグインを再度追加します。

例:

$ cd <your_Cordova_app_folder>$ cordova plugin rm com.salesforce$ cordova plugin add https://github.com/forcedotcom/SalesforceMobileSDK-CordovaPlugin$ cordova prepare

Android ネイティブアプリケーションを 3.0 から 3.1 に移行するAndroid ネイティブアプリケーションを Salesforce Mobile SDK 3.0 からバージョン 3.1 にアップグレードするには、次の手順を実行します。1. Eclipse で Mobile SDK プロジェクトワークスペースを開きます。2. 既存の Cordova プロジェクトを Mobile SDK 3.1 Cordova プロジェクトに置き換えます。3. 既存の SalesforceSDK プロジェクトを新しい SalesforceSDK プロジェクトに置き換えます。4. アプリケーションで SmartStore を使用する場合は、既存の SmartStore プロジェクトを新しい SmartStore プロ

ジェクトに置き換えます。5. アプリケーションでSmartSyncを使用する場合は、既存のSmartSyncプロジェクトを新しいSmartSyncプロジェ

クトに置き換えます。6. プロジェクトエクスプローラで、プロジェクトを右クリックして [Properties (プロパティ)] を選択します。7. 左パネルで、[Android] を選択します。8. [Library (ライブラリ)] セクションで、既存の SalesforceSDK エントリをワークスペースの新しい SalesforceSDK プ

ロジェクトに置き換えます。9. アプリケーションで SmartStore を使用する場合は、SmartStore プロジェクトでステップ 8 を繰り返します。10. アプリケーションで SmartSync を使用する場合は、SmartSync プロジェクトでステップ 8 を繰り返します。

iOS ネイティブアプリケーションを 3.0 から 3.1 に移行するMobile SDK 3.1 への移行は、わずかな作業で実行できます。現在サポートされている Xcode の最小バージョンは6.0 です。また、既存のバイナリパッケージの更新に加えて、新しい SalesforceSDKCommon

(SalesforceSDKCommon-[Debug/Release].zip) パッケージが追加されました。このパッケージには、下位レベルのネットワークおよびセキュリティユーティリティが含まれています。Mobile SDK 3.0 アプリケーションをMobile SDK 3.1 にアップグレードするには、「Mobile SDK ライブラリパッケージを 3.0 から 3.1 に更新する」の手順を実行します。

Mobile SDK ライブラリパッケージを 3.0 から 3.1 に更新するライブラリパッケージを更新するには、アプリケーションの Xcode プロジェクトの Dependencies フォルダを削除して再作成し、新しいライブラリをこのフォルダに追加します。

410

Android ネイティブアプリケーションを 3.0 から 3.1 に移行する

以前のリリースからの移行

1. SalesforceMobileSDK-iOS-Distribution リポジトリ (https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Distribution) から次のバイナリパッケージをダウンロードします。• MKNetworkKit-iOS-Release.zip

• SalesforceRestAPI-Release.zip

• SalesforceNetworkSDK-Release.zip

• SalesforceOAuth-Release.zip

• SalesforceSDKCommon-Release.zip

• SalesforceSDKCore-Release.zip

• SalesforceSecurity-Release.zip

• SmartSync-Release.zip

2. また、配布リポジトリの ThirdParty フォルダリンクから次のフォルダもダウンロードします。• SalesforceCommonUtils

• openssl

• sqlcipher

3. Xcode で Mobile SDK プロジェクトを開きます。4. プロジェクトナビゲータで、Dependencies フォルダを見つけます。5. Ctrl キーを押しながらフォルダをクリックします。[Delete (削除)] を選択し、[Move to Trash (ゴミ箱に移動)]

を選択します。6. Xcode プロジェクトで、アプリケーションフォルダの下に Dependencies フォルダを再作成します。7. Dependencies フォルダに、ステップ 1 の新しいパッケージを解凍し、ステップ 2 のフォルダをコピーします。8. プロジェクトナビゲータで、Ctrl キーを押しながらアプリケーションフォルダをクリックし、[Add Files to

"<App Name>"... (「<アプリケーション名>」にファイルを追加...)] を選択します。9. Dependencies フォルダを選択し、追加したフォルダで [Create groups (グループを作成)] が選択されているこ

とを確認します。10. [追加] をクリックします。

411

iOS ネイティブアプリケーションを 3.0 から 3.1 に移行する

以前のリリースからの移行

第 17 章 リファレンス

リファレンスドキュメントは、GitHub で提供されています。トピック:• iOS の場合:• REST API リソース

– SalesforceSDKCore ライブラリリファレンス(http://forcedotcom.github.io/SalesforceMobileSDK-iOS/Documentation/SalesforceSDKCore/html/index.html)

• iOS アーキテクチャ• Android アーキテク

チャ – SalesforceRestAPI ライブラリリファレンス(http://forcedotcom.github.io/SalesforceMobileSDK-iOS/Documentation/SalesforceRestAPI/html/index.html)• Files API リファレン

ス – SalesforceNetwork ライブラリリファレンス(http://forcedotcom.github.io/SalesforceMobileSDK-iOS/Documentation/SalesforceNetwork/html/index.html)• forceios パラメータ

– SmartStore ライブラリリファレンス(http://forcedotcom.github.io/SalesforceMobileSDK-iOS/Documentation/SmartStore/html/index.html)

• forcedroid パラメータ

– SmartSync ライブラリリファレンス(http://forcedotcom.github.io/SalesforceMobileSDK-iOS/Documentation/SmartSync/html/index.html)

– SalesforceHybridSDK ライブラリリファレンス(http://forcedotcom.github.io/SalesforceMobileSDK-iOS/Documentation/SalesforceHybridSDK/html/index.html)

– SalesforceReact ライブラリリファレンス(http://forcedotcom.github.io/SalesforceMobileSDK-iOS/Documentation/SalesforceReact/html/index.html)

• Android: http://forcedotcom.github.com/SalesforceMobileSDK-Android/index.html

412

REST API リソース

Salesforce Mobile SDKは、ラッパーを提供して REST APIコールを簡略化します。メソッドをコールし、正しいパラメータを指定するだけで十分です。残りの処理は自動的に行われます。次の表に、使用可能なリソースとその用途を示します。詳細は、developer.force.com/page/REST_APIを参照してください。

説明URIリソース名

バージョン、表示ラベル、および各バージョンのルートへのリンクなど、現在使用可能な

/Versions

各 Salesforceバージョンの概要情報をリストします。

リソース名および URI を含む、指定された API

バージョンで使用可能なリソースをリストします。

/vXX.X/Resourcesby Version

組織のデータで使用可能なオブジェクトとそのメタデータをリストします。

/vXX.X/sobjects/DescribeGlobal

指定されたオブジェクトの個別のメタデータを説明します。特定のオブジェクトの新規レコードの作成にも使用できます。

/vXX.X/sobjects/S オブジェクト/sObjectBasicInformation

指定されたオブジェクトのすべてのレベルで、個別のメタデータを完全に説明します。

/vXX.X/sobjects/S オブジェクト/describe/SObjectDescribe

指定されたオブジェクト ID に基づいてレコードにアクセスします。レコードを取得、更

/vXX.X/sobjects/S オブジェクト/id/sObjectRows

新、または削除します。このリソースは、項目値の取得にも使用できます。

指定された外部 ID 項目の値に基づいて、新しいレコードを作成するか、既存のレコードを更新 (レコードを Upsert) します。

/vXX.X/sobjects/SObjectName/fieldName/fieldValuesObjectRows byExternalID

ユーザパスワードを設定またはリセットしたり、ユーザパスワードに関する情報を取得したりします。

/vXX.X/sobjects/User/ユーザ ID/password

/vXX.X/sobjects/SelfServiceUser/セルフサービスユーザ ID/password

sObjectUserPassword

指定された SOQL クエリを実行します。/vXX.X/query/?q=soqlQuery

指定されたSOSL検索を実行します。検索文字列は URL 符号化されている必要があります。

/vXX.X/search/?s=soslSearch

413

REST API リソースリファレンス

説明URIリソース名

クエリ文字列に含まれるオブジェクトの検索結果レイアウトに関する情報を返します。こ

/vXX.X/search/layout/?q=カンマ区切りのオブジェクトリスト

SearchResultLayouts のコールでは、検索結果ページに列として表

示される項目のリスト、最初のページに表示される行数、および検索結果ページで使用されるラベルがオブジェクトごとに返されます。

ログインユーザのデフォルトのグローバル検索範囲内にあるオブジェクトの順序付きリス

/vXX.X/search/scopeOrderSearchScopeand Order トを返します。グローバル検索は、操作する

オブジェクトとそれらを操作する頻度を追跡し、それに基づいて検索結果を編成します。最もよく使用されるオブジェクトは、リストの最上部に表示されます。

iOS アーキテクチャ

Mobile SDK は基本的に 1 つのライブラリで、次のモジュールと連動し、公開されています。• SalesforceHybridSDK — Mobile SDK Cordova プラグインを定義します。ハイブリッドアプリケーションで

のみ使用します。• SalesforceNetwork — REST API コールを容易にします。CocoaPods を使用して入手するか、Mobile SDK GitHub

リポジトリから入手できるサードパーティライブラリが必要です。• SalesforceReact — Mobile SDK 機能に対するネイティブブリッジ。React Native アプリケーションでのみ使

用します。• SalesforceRestAPI — Salesforce REST API コール用の Mobile SDK ラッパー。• SalesforceSDKCore — OAuth 認証とパスコードを実装します。• SmartStore — Mobile SDK の安全なオフラインストレージソリューション。• SmartSync — Mobile SDK のオフライン同期ソリューション。forceios を使用してネイティブアプリケーションを作成する場合、CocoaPods は指定したアプリケーション種別に基づいて必要なモジュールを組み込みます。SalesforceMobileSDK-iOS Git リポジトリのコピーを使用してネイティブアプリケーションを作成する場合、プロジェクトはこれらのモジュールを動的ライブラリとして使用します。

iOS のネイティブ REST API クラス次の Objective-C API を使用して、ネイティブアプリケーションで Salesforce データにアクセスします。• SFRestAPI クラス

414

iOS アーキテクチャリファレンス

• SFRestAPI (Blocks) カテゴリ• SFRestRequest クラス• SFRestAPI (QueryBuilder) カテゴリ• SFRestDelegate プロトコル

SFRestAPISFRestAPI は、REST 要求を行うためのエントリポイントであり、通常、[SFRestAPI sharedInstance] を介してシングルトンインスタンスとしてアクセスされます。このオブジェクトから、次のような既定の多くの標準クエリを簡単に作成できます。SFRestRequest* request = [[SFRestAPI sharedInstance]requestForUpdateWithObjectType:@"Contact"

objectId:contactIdfields:updatedFields];

次のコマンドを使用して、要求を開始できます。[[SFRestAPI sharedInstance] send:request delegate:self];

SFRestAPI (ブロック)SFRestAPI クラスのこのカテゴリ拡張を使用して、ブロックをコールバックメカニズムとして指定します。次に例を示します。NSMutableDictionary *fields = [NSMutableDictionary dictionaryWithObjectsAndKeys:

@"John", @"FirstName",@"Doe", @"LastName",nil];

[[SFRestAPI sharedInstance] performCreateWithObjectType:@"Contact"fields:fieldsfailBlock:^(NSError *e) {

NSLog(@"Error: %@", e);}completeBlock:^(NSDictionary *d) {

NSLog(@"ID value for object: %@", [d objectForKey:@"id"]);}];

SFRestRequestSFRestAPI で提供される標準 REST 要求だけでなく、直接 SFRestRequest メソッドを使用して独自の要求を作成することもできます。NSString *path = @"/v31.0";SFRestRequest* request = [SFRestRequest

requestWithMethod:SFRestMethodGET path:path queryParams:nil];

415

iOS のネイティブ REST API クラスリファレンス

SFRestAPI (QueryBuilder)このカテゴリ拡張には、SOQL および SOSL のクエリ文字列を作成するためのユーティリティメソッドが備えられています。例:

NSString *soqlQuery =[SFRestAPI SOQLQueryWithFields:[NSArray arrayWithObjects:@"Id", @"Name", @"Company",@"Status", nil]

sObject:@"Lead"where:nillimit:10];

NSString *soslQuery =[SFRestAPISOSLSearchWithSearchTerm:@"all of these will be escaped:~{]"

objectScope:[NSDictionarydictionaryWithObject:@"WHERE isactive=true

ORDER BY lastnameasc limit 5"

forKey:@"User"]];

SFRestDelegateこのプロトコルを実装するクラスは、REST 応答の対象として機能できます。このプロトコルは、さまざまな要求の状況を処理するための 4 つの抽象メソッドを定義します。これらのメソッドを実装する場合は、dispatch_async(dispatch_get_main_queue(), ^{...}ブロックの UI 要素にアクセスするコードを必ずラップしてください。例:

- (void)request:(SFRestRequest *)request didLoadResponse:(id)dataResponse {dispatch_async(dispatch_get_main_queue(), ^{

_tfResult.backgroundColor =[UIColor colorWithRed:1.0 green:204/255.0 blue:102/255.0 alpha:1.0];

_tfResponseFor.text = [self formatRequest:request];_tfResult.text = [dataResponse description];

});}

- (void)request:(SFRestRequest*)request didFailLoadWithError:(NSError*)error {dispatch_async(dispatch_get_main_queue(), ^{

_tfResult.backgroundColor = [UIColor redColor];_tfResponseFor.text = [self formatRequest:request];_tfResult.text = [error description];

});}

- (void)requestDidCancelLoad:(SFRestRequest *)request {dispatch_async(dispatch_get_main_queue(), ^{

_tfResult.backgroundColor = [UIColor redColor];_tfResponseFor.text = [self formatRequest:request];_tfResult.text = @"Request was cancelled";

});}

416

iOS のネイティブ REST API クラスリファレンス

- (void)requestDidTimeout:(SFRestRequest *)request {dispatch_async(dispatch_get_main_queue(), ^{

_tfResult.backgroundColor = [UIColor redColor];_tfResponseFor.text = [self formatRequest:request];_tfResult.text = @"Request timedout";

});}

Android アーキテクチャ

Salesforce Mobile SDK は、ライブラリプロジェクトとして提供されています。Android アプリケーションは、アプリケーションプロジェクトから SalesforceSDK プロジェクトを参照します。「Android アーキテクチャ」を参照してください。

Android パッケージおよびクラスAndroid Mobile SDK の Java ソースファイルは、libs/SalesforceSDK/src にあります。

最上位パッケージのカタログ

説明パッケージ名

ユーザアカウントを管理するためのクラス。com.salesforce.androidsdk.accounts

すべての Mobile SDK アプリケーションのエントリポイントクラスである SalesforceSDKManagerが含まれ

com.salesforce.androidsdk.app

ています。このパッケージには、内部で使用するアプリケーションユーティリティクラスもあります。

内部的にのみ使用されます。ログイン、OAuth 認証、HTTP アクセスを処理します。

com.salesforce.androidsdk.auth

com.salesforce.androidsdk.config

ネイティブコードと Javascript コード間のブリッジを作成するためにハイブリッドアプリケーションで使用さ

com.salesforce.androidsdk.phonegap

れる内部クラス。Mobile SDK Javascript ライブラリを実装するプラグインが含まれています。SDK アプリケーション内に独自の Javascript プラグインを実装する場合、ForcePlugin を拡張して、抽象 execute() 関数を実装します。「ForcePlugin クラス」を参照してください。

ハイブリッドプロジェクト用の Mobile SDK アプリケーション。

com.salesforce.androidsdk.phonegap.app

Mobile SDK Cordova プラグインで使用されるプラグイン。com.salesforce.androidsdk.phonegap.plugin

417

Android アーキテクチャリファレンス

説明パッケージ名

ハイブリッドコンテナの Web ビュー実装。com.salesforce.androidsdk.phonegap.ui

ハイブリッドテスト。com.salesforce.androidsdk.phonegap.util

このパッケージのコンポーネントは、Salesforce転送通知の対象となるデバイスを登録および登録解除しま

com.salesforce.androidsdk.push

す。次に、これらのコンポーネントは、Google Cloud

Messaging (GCM) を通じて Salesforce 接続アプリケーションから通知を受信します。「転送通知と Mobile SDK」を参照してください。

Mobile SDK アプリケーションの React Native 実装。com.salesforce.androidsdk.reactnative

React Native 用の Mobile SDK アプリケーション。com.salesforce.androidsdk.reactnative.app

React Native アプリケーションの Mobile SDK 機能に対するネイティブブリッジ。

com.salesforce.androidsdk.reactnative.bridge

REST API アクティビティを処理するためのクラス。これらのクラスは Salesforce インスタンスとの通信を管理

com.salesforce.androidsdk.rest

し、REST 要求の HTTP プロトコルを処理します。要求の送信に使用できる同期メソッドや非同期メソッドについての詳細は、ClientManagerおよび RestClient

を参照してください。

Files REST API の要求および応答を処理するためのクラス。

com.salesforce.androidsdk.rest.files

パスコードおよび暗号化を処理する内部クラス。独自のキーを提供している場合、Encryptor クラスを使

com.salesforce.androidsdk.security

用してハッシュを生成できます。Encryptor を参照してください。

SmartStore オフラインストレージソリューション。com.salesforce.androidsdk.smartstore

SmartStore アプリケーション。com.salesforce.androidsdk.smartstore.app

データベース実装。com.salesforce.androidsdk.smartstore.store

SmartStoreInspector アクティビティ。com.salesforce.androidsdk.smartstore.ui

SmartSync オフライン同期ソリューション。com.salesforce.androidsdk.smartsync

複数の SmartSync ユーザアカウントを管理します。com.salesforce.androidsdk.smartsync.accounts

SmartSync アプリケーション。com.salesforce.androidsdk.smartsync.app

メタデータ、キャッシュ、および同期のマネージャクラス。

com.salesforce.androidsdk.smartsync.manager

418

Android パッケージおよびクラスリファレンス

説明パッケージ名

Salesforceオブジェクト、その種別、およびレイアウトを表すクラス。

com.salesforce.androidsdk.smartsync.model

SOSL、SOQL、およびその他の同期の基本クラス。com.salesforce.androidsdk.smartsync.util

アクティビティ (ログインアクティビティなど)。com.salesforce.androidsdk.ui

ハイブリッドアプリケーションのアクティビティの基本クラス。

com.salesforce.androidsdk.ui.sfhybrid

ネイティブアプリケーションのアクティビティの基本クラス。

com.salesforce.androidsdk.ui.sfnative

ユーティリティおよびテストクラスが含まれています。これらのクラスの大部分は内部で使用されますが、いくつかの重要な例外もあります。

com.salesforce.androidsdk.util

• EventObserverインターフェースを実装して、任意のイベントタイプを傍受できます。

• EventsListenerQueue クラスは、独自のテストを実装する場合に便利です。

• EventsObservableのソースコードを参照して、サポートされているすべてのイベントタイプのリストを確認できます。

クラスの説明は、『Salesforce Mobile SDK Android Reference』を参照してください。

Android リソースリソースは /res にあります。

drawable-hdpi

使用ファイル

サーバピッカー画面sf__edit_icon.png

ログイン画面sf__highlight_glare.png

ネイティブアプリケーションアイコンsf__icon.png

419

Android リソースリファレンス

drawable-ldpi

使途ファイル

アプリケーションアイコンsf__icon.png

drawable-mdpi

使途ファイル

サーバピッカー画面sf__edit_icon.png

ログイン画面sf__highlight_glare.png

アプリケーションアイコンsf__ic_refresh_sync_anim0.png

アプリケーションアイコンsf__icon.png

drawable-xhdpi

使途ファイル

ネイティブアプリケーションアイコンsf__icon.png

drawable-xlarge

使途ファイル

ログイン画面 (タブレット)sf__header_bg.png

ログイン画面 (タブレット)sf__header_drop_shadow.xml

ログイン画面 (タブレット)sf__header_left_border.xml

ログイン画面 (タブレット)sf__header_refresh.png

ログイン画面 (タブレット)sf__header_refresh_press.png

ログイン画面 (タブレット)sf__header_refresh_states.xml

ログイン画面 (タブレット)sf__header_right_border.xml

ログイン画面 (タブレット)sf__login_content_header.xml

ログイン画面 (タブレット)sf__nav_shadow.png

ログイン画面 (タブレット)sf__oauth_background.png

ログイン画面 (タブレット)sf__oauth_container_dropshadow.9.png

420

Android リソースリファレンス

使途ファイル

ログイン画面 (タブレット)sf__progress_spinner.xml

ログイン画面 (タブレット)sf__refresh_loader.png

ログイン画面 (タブレット)sf__toolbar_background.xml

drawable-xlarge-port

使途ファイル

ログイン画面 (タブレット)sf__oauth_background.png

drawable-xxhdpi

使途ファイル

ネイティブアプリケーションアイコンsf__icon.png

drawable

使途ファイル

ログイン画面sf__header_bg.png

ログイン画面sf__progress_spinner.xml

ログイン画面sf__toolbar_background.xml

layout

使途ファイル

アカウントの切り替え画面sf__account_switcher.xml

サーバピッカー画面sf__custom_server_url.xml

ログイン画面sf__login.xml

ユーザがアプリケーションデータをクリアしたり、ログアウトしたりできる画面

sf__manage_space.xml

PIN 画面sf__passcode.xml

サーバピッカー画面 (廃止)sf__server_picker.xml

サーバピッカー画面sf__server_picker_list.xml

421

Android リソースリファレンス

menu

使途ファイル

[接続を追加] ダイアログsf__clear_custom_url.xml

ログインメニュー (電話)sf__login.xml

values

使途ファイル

接続アプリケーションの構成設定bootconfig.xml

色sf__colors.xml

Dimensionssf__dimens.xml

SDK 文字列sf__strings.xml

スタイルsf__style.xml

その他の文字列 (アプリケーション名)strings.xml

xml

使途ファイル

アプリケーションで使用するアカウントの設定authenticator.xml

サーバ設定servers.xml

Files API リファレンス

Files 機能の API アクセスは、Android、iOS、および各種ハイブリッドで使用できます。

FileRequests メソッド (Android)すべての FileRequests メソッドは静的で、それぞれ RestRequest インスタンスを返します。RestClient.sendAsync()または RestClient.sendSync()メソッドを使用して、RestRequestオブジェクトをサーバに送信します。「REST API の使用」を参照してください。REST リクエストボディおよびレスポンスボディについての詳細は、「Chatter REST APIリソース」の「Files リソース」(http://www.salesforce.com/us/developer/docs/chatterapi) を参照してください。

422

Files API リファレンスリファレンス

ownedFilesList指定されたユーザが所有するファイルのリストを取得する要求を生成します。結果の 1 ページを返します。署名

public static RestRequest ownedFilesList(String userId, Integer pageNum);

パラメータ

説明型名前

ユーザの ID。null の場合、コンテキスト (ログイン) ユーザの ID が使用されます。

StringuserId

取得する結果のページの開始値 0 のインデックス。null の場合、最初のページを取得します。

IntegerpageNum

例RestRequest request = FileRequests.ownedFilesList(null, null);

filesInUsersGroups指定されたユーザの所属グループが所有するファイルのリストを取得する要求を生成します。署名

public static RestRequest filesInUsersGroups(String userId, Integer pageNum);

パラメータ

説明データ型名前

ユーザの ID。null の場合、コンテキスト (ログイン) ユーザの ID が使用されます。

StringuserId

取得する結果のページの開始値 0 のインデックス。null の場合、最初のページを取得します。

IntegerpageNum

例RestRequest request = FileRequests.filesInUsersGroups(null, null);

filesSharedWithUser指定されたユーザと共有されたファイルのリストを取得する要求を生成します。署名

public static RestRequest filesSharedWithUser(String userId, Integer pageNum);

423

FileRequests メソッド (Android)リファレンス

パラメータ

説明データ型名前

ユーザの ID。null の場合、コンテキスト (ログイン) ユーザの ID が使用されます。

StringuserId

取得する結果のページの開始値 0 のインデックス。null の場合、最初のページを取得します。

IntegerpageNum

例RestRequest request = FileRequests.filesSharedWithUser(null, null);

fileDetails特定のバージョンのファイルの詳細を取得できる要求を生成します。署名

public static RestRequest fileDetails(String sfdcId, String version);

パラメータ

説明データ型名前

ファイルの ID。null の場合、IllegalArgumentException

が発生します。StringsfdcId

取得するバージョン。null の場合、最新バージョンを取得します。

Stringversion

例String id = <some_file_id>;RestRequest request = FileRequests.fileDetails(id, null);

batchFileDetails複数のファイルの詳細を取得できる要求を生成します。署名

public static RestRequest batchFileDetails(List sfdcIds);

424

FileRequests メソッド (Android)リファレンス

パラメータ

説明データ型名前

1 つ以上のファイルの ID のリスト。リストの ID がひとつでも null の場合、IllegalArgumentExceptionが発生します。

ListsfdcIds

例List<String> ids = Arrays.asList("id1", "id2", ...);RestRequest request = FileRequests.batchFileDetails(ids);

fileRendition指定されたファイルのページの表示されたプレビューを取得できる要求を生成します。署名

public static RestRequest fileRendition(String sfdcId,String version,RenditionType renditionType,Integer pageNum);

パラメータ

説明データ型名前

表示されるファイルの ID。null の場合、IllegalArgumentException が発生します。

StringsfdcId

取得するバージョン。null の場合、最新バージョンを取得します。

Stringversion

返される変換の種別を指定します。使用できる値は次のとおりです。

RenditionTyperenditionType

• PDF

• FLASH

• SLIDE

• THUMB120BY90

• THUMB240BY180

• THUMB720BY480

null の場合、THUMB120BY90 が使用されます。

取得するページの開始値 0 のインデックス。null の場合、最初のページを取得します。

IntegerpageNum

425

FileRequests メソッド (Android)リファレンス

例String id = <some_file_id>;RestRequest request = FileRequests.fileRendition(id, null, "PDF", 0);

fileContents指定されたファイルのバイナリコンテンツを取得できる要求を生成します。署名

public static RestRequest fileContents(String sfdcId, String version);

パラメータ

説明データ型名前

表示されるファイルの ID。null の場合、IllegalArgumentException が発生します。

StringsfdcId

取得するバージョン。null の場合、最新バージョンを取得します。

Stringversion

例String id = <some_file_id>;RestRequest request = FileRequests.fileContents(id, null);

fileShares指定されたファイルを共有するエンティティのリストからページを取得できる要求を生成します。署名

public static RestRequest fileShares(String sfdcId, Integer pageNum);

パラメータ

説明データ型名前

表示されるファイルの ID。null の場合、IllegalArgumentException が発生します。

StringsfdcId

取得する結果のページの開始値 0 のインデックス。null の場合、最初のページを取得します。

IntegerpageNum

例String id = <some_file_id>;RestRequest request = FileRequests.fileShares(id, null);

426

FileRequests メソッド (Android)リファレンス

addFileShare指定されたエンティティと指定のファイルを共有できる要求を生成します。署名

public static RestRequest addFileShare(String fileId, String entityId,String shareType);

パラメータ

説明データ型名前

共有されるファイルの ID。null の場合、IllegalArgumentException が発生します。

StringfileId

ファイルを共有するユーザまたはグループの ID。null の場合、IllegalArgumentException が発生します。

StringentityID

共有種別。有効な値は「V」(表示) と「C」(コラボレーション) です。

StringshareType

例String idFile = <some_file_id>;String idEntity = <some_user_or_group_id>;RestRequest request = FileRequests.addFileShare(idFile, idEntity, "V");

deleteFileShare指定されたファイル共有を削除できる要求を生成します。署名

public static RestRequest deleteFileShare(String shareId);

パラメータ

説明データ型名前

削除されるファイル共有の ID。null の場合、IllegalArgumentException が発生します。

StringshareId

例String id = <some_fileShare_id>;RestRequest request = FileRequests.deleteFileShare(id);

427

FileRequests メソッド (Android)リファレンス

uploadFileローカルファイルをサーバにアップロードできる要求を生成します。この要求により、バージョン 1 のファイルがサーバで作成されます。署名

public static RestRequest uploadFile(File theFile,String name, String description, String mimeType)throws UnsupportedEncodingException;

パラメータ

説明データ型名前

サーバにアップロードされるローカルファイルのパス。FiletheFile

ファイルの名前。Stringname

ファイルの説明。Stringdescription

ファイルの MIME タイプ (タイプがわかっている場合)。それ以外の場合は null。

StringmimeType

発生する例外UnsupportedEncodingException

例RestRequest request = FileRequests.uploadFile("/Users/JayVee/Documents/",

"mypic.png", "Profile pic", "image/png");

SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)iOS ネイティブアプリケーションでは、SFRestAPI (Files)カテゴリがファイル要求メソッドを定義します。要求メッセージを SFRestAPI シングルトンに送信します。SFRestRequest *request = [[SFRestAPI sharedInstance] requestForOwnedFilesList:nil page:0];

各メソッドは SFRestRequest インスタンスを返します。SFRestAPI シングルトンを再度使用して、要求オブジェクトをサーバに送信します。次の例では、コール元クラス (self) が代理オブジェクトですが、SFRestDelegate を実装する他のオブジェクトを指定することもできます。[[SFRestAPI sharedInstance] send:request delegate:self];

requestForOwnedFilesList:page:指定されたユーザが所有するファイルのリストを取得する要求を生成します。結果の 1 ページを返します。

428

SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)リファレンス

署名- (SFRestRequest *)requestForOwnedFilesList:(NSString *)userId

page:(NSUInteger)page;

パラメータ

説明データ型名前

ユーザの ID。nil の場合、コンテキスト (ログイン) ユーザの ID が使用されます。

NSString *userId

取得するページの開始値 0 のインデックス。nil の場合、最初のページを取得します。

NSUIntegerpage

例SFRestRequest *request =

[[SFRestAPI sharedInstance] requestForOwnedFilesList:nilpage:0];

requestForFilesInUsersGroups:page:指定されたユーザの所属グループが所有するファイルのリストを取得する要求を生成します。署名

- (SFRestRequest *)requestForFilesInUsersGroups:(NSString *)userId

page:(NSUInteger)page;

パラメータ

説明データ型名前

ユーザの ID。nil の場合、コンテキスト (ログイン) ユーザの ID が使用されます。

NSString *userId

取得するページの開始値 0 のインデックス。nil の場合、最初のページを取得します。

NSUIntegerpage

例SFRestRequest *request = [[SFRestAPI sharedInstance]

requestForFilesInUsersGroups:nilpage:0];

429

SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)リファレンス

requestForFilesSharedWithUser:page:指定されたユーザと共有されたファイルのリストを取得する要求を生成します。署名

- (SFRestRequest *)requestForFilesSharedWithUser:(NSString *)userId

page:(NSUInteger)page;

パラメータ

説明データ型名前

ユーザの ID。nil の場合、コンテキスト (ログイン) ユーザの ID が使用されます。

NSString *userId

取得するページの開始値 0 のインデックス。nil の場合、最初のページを取得します。

NSUIntegerpage

例SFRestRequest *request =

[[SFRestAPI sharedInstance] requestForFilesSharedWithUser:nilpage:0];

requestForFileDetails:forVersion:特定のバージョンのファイルの詳細を取得できる要求を生成します。署名

- (SFRestRequest *)requestForFileDetails:(NSString *)sfdcId

forVersion:(NSString *)version;

パラメータ

説明データ型名前

ファイルの ID。nil の場合、要求が失敗します。NSString *sfdcId

取得するバージョン。nil の場合、最新バージョンを取得します。

NSString *version

例NSString *id = [NSString stringWithString:@"some_file_id"];SFRestRequest *request =

[[SFRestAPI sharedInstance] requestForFileDetails:idforVersion:nil];

430

SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)リファレンス

requestForBatchFileDetails:複数のファイルの詳細を取得できる要求を生成します。署名

- (SFRestRequest *)requestForBatchFileDetails:(NSArray *)sfdcIds;

パラメータ

説明データ型名前

1 つ以上のファイルの ID の配列。ID は文字列として表されます。

NSArray *sfdcIds

例NSArray *ids = [NSArray arrayWithObject:@"id1",@"id2",...,nil];SFRestRequest *request =

[[SFRestAPI sharedInstance] requestForBatchFileDetails:ids];

requestForFileRendition:version:renditionType:page:指定されたファイルのページの表示されたプレビューを取得できる要求を生成します。署名

- (SFRestRequest *)requestForFileRendition:(NSString *)sfdcId

version:(NSString *)versionrenditionType:(NSString *)renditionType

page:(NSUInteger)page;

パラメータ

説明データ型名前

表示されるファイルの ID。nil の場合、要求が失敗します。NSString *sfdcId

取得するバージョン。nil の場合、最新バージョンを取得します。

NSString *version

返される変換の種別を指定します。使用できる値は次のとおりです。

NSString *renditionType

• "PDF"

• "FLASH"

• "SLIDE"

• "THUMB120BY90"

• "THUMB240BY180"

• "THUMB720BY480"

431

SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)リファレンス

説明データ型名前

nil の場合、THUMB120BY90 が使用されます。

取得するページの開始値 0 のインデックス。nil の場合、最初のページを取得します。

NSUIntegerpage

例NSString *id = [NSString stringWithString:@"some_file_id"];SFRestRequest *request =

[[SFRestAPI sharedInstance] requestForFileRendition:idversion:nil

renditionType:nilpage:nil];

requestForFileContents:version:指定されたファイルのバイナリコンテンツを取得できる要求を生成します。署名

- (SFRestRequest *)requestForFileContents:(NSString *) sfdcId

version:(NSString*) version;

パラメータ

説明データ型名前

表示されるファイルの ID。nil の場合、要求が失敗します。NSString *sfdcId

取得するバージョン。nil の場合、最新バージョンを取得します。

NSString *version

例NSString *id = [NSString stringWithString:@"some_file_id"];SFRestRequest *request =

[[SFRestAPI sharedInstance] requestForFileContents:idversion:nil];

requestForFileShares:page:指定されたファイルを共有するエンティティのリストからページを取得できる要求を生成します。署名

- (SFRestRequest *)requestForFileShares:(NSString *)sfdcId

page:(NSUInteger)page;

432

SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)リファレンス

パラメータ

説明データ型名前

表示されるファイルの ID。nil の場合、要求が失敗します。NSString *sfdcId

取得するページの開始値 0 のインデックス。nil の場合、最初のページを取得します。

NSUIntegerpage

例NSString *id = [NSString stringWithString:@"some_file_id"];SFRestRequest *request =

[[SFRestAPI sharedInstance] requestForFileShares:idpage:nil];

requestForAddFileShare:entityId:shareType: メソッド指定されたエンティティと指定のファイルを共有できる要求を生成します。署名

- (SFRestRequest *)requestForAddFileShare:(NSString *)fileId

entityId:(NSString *)entityIdshareType:(NSString*)shareType;

パラメータ

説明データ型名前

共有されるファイルの ID。nil の場合、要求が失敗します。NSString *fileId

ファイルを共有するユーザまたはグループの ID。nil の場合、要求が失敗します。

NSString *entityId

共有種別。有効な値は「V」(表示) と「C」(コラボレーション) です。

NSString *shareType

例NSString *id = [NSString stringWithString:@"some_file_id"];NSString *entId = [NSString stringWithString:@"some_entity_id"];SFRestRequest *request =

[[SFRestAPI sharedInstance] requestForAddFileShare:identityId:entIdshareType:@"V"];

433

SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)リファレンス

requestForDeleteFileShare:指定されたファイル共有を削除できる要求を生成します。署名

- (SFRestRequest *)requestForDeleteFileShare:(NSString *)shareId;

パラメータ

説明データ型名前

削除されるファイル共有の ID。nil の場合、要求が失敗します。

NSString *shareId

例NSString *id = [NSString stringWithString:@"some_fileshare_id"];SFRestRequest *request =

[[SFRestAPI sharedInstance] requestForDeleteFileShare:id];

requestForUploadFile:name:description:mimeType: メソッドローカルファイルをサーバにアップロードできる要求を生成します。この要求により、バージョン 1 の新しいファイルがサーバで作成されます。署名

- (SFRestRequest *)requestForUploadFile:(NSData *)data

name:(NSString *)namedescription:(NSString *)description

mimeType:(NSString *)mimeType;

パラメータ

説明データ型名前

サーバにアップロードするデータ。NSData *data

ファイルの名前。NSString *name

ファイルの説明。NSString *description

ファイルの MIME タイプ (タイプがわかっている場合)。それ以外の場合は、nil。

NSString *mimeType

NSData *data = [NSData dataWithContentsOfFile:@"/Users/JayVee/Documents/mypic.png"];

434

SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)リファレンス

SFRestRequest *request =[[SFRestAPI sharedInstance] requestForUploadFile:data

name:@"mypic.png"description:@"Profile pic"

mimeType:@"image/png"];

ハイブリッドアプリケーションの Files メソッドFiles API のハイブリッドメソッドは、forcetk.mobilesdk.jsライブラリにあります。次の参照トピックの例では、次のようなローカル ftkclient 変数を宣言していることを前提としています。var ftkclient = new forcetk.Client(creds.clientId, creds.loginUrl, creds.proxyUrl, reauth);

メモ: smartsync.js では、forcetk.Client オブジェクトは Force.forcetkClient としてラップされます。SmartSync アプリケーションでは、いずれかのクライアントを自由に使用できます。ただし、Force.forcetkClient でコールされる REST API メソッドは、JavaScript promise を返すという点でそれらのforcetk.Clientの類似カテゴリとは異なります。Force.forcetkClientを使用する場合、成功コールバックとエラーコールバックを必要とする例を次のように再度書式設定します。Force.forcetkClient.ownedFilesList(null, null)

.done(function(response) {/* do something with the returned JSON data */})

.fail(function(error) { alert("Error!");});

ownedFilesList メソッド指定されたユーザが所有するファイルのリストからページを返します。署名

forcetk.Client.prototype.ownedFilesList =function(userId, page, callback, error)

パラメータ

説明名前

既存のユーザの ID。null の場合、コンテキスト (現在ログインしている) ユーザの ID が使用されます。

userId

取得する結果のページの開始値 0 のインデックス。null の場合、最初のページを取得します。

page

サーバ応答を非同期で受信して処理する関数。callback

サーバエラーを処理する関数。error

435

ハイブリッドアプリケーションの Files メソッドリファレンス

例ftkclient.ownedFilesList(null, null,

function(response){ /* do something with the returned JSON data */},function(error){ alert("Error!");}

);

filesInUsersGroups メソッド指定されたユーザの所属グループが所有するファイルのリストからページを返します。署名

forcetk.Client.prototype.filesInUsersGroups =function(userId, page, callback, error)

パラメータ

説明名前

既存のユーザの ID。null の場合、コンテキスト (現在ログインしている) ユーザの ID が使用されます。

userId

取得する結果のページの開始値 0 のインデックス。null の場合、最初のページを取得します。

page

サーバ応答を非同期で受信して処理する関数。callback

サーバエラーを処理する関数。error

例ftkclient.filesInUsersGroups(null, null,

function(response){/* do something with the returned JSON data */

},function(error){ alert("Error!");}

);

filesSharedWithUser メソッド指定されたユーザと共有されたファイルのリストからページを返します。署名

forcetk.Client.prototype.filesSharedWithUser =function(userId, page, callback, error)

436

ハイブリッドアプリケーションの Files メソッドリファレンス

パラメータ

説明名前

既存のユーザの ID。null の場合、コンテキスト (現在ログインしている) ユーザの ID が使用されます。

userId

取得する結果のページの開始値 0 のインデックス。null の場合、最初のページを取得します。

page

サーバ応答を非同期で受信して処理する関数。callback

サーバエラーを処理する関数。error

例ftkclient.filesSharedWithUser(null, null,

function(response){/* do something with the returned JSON data */

},function(error){ alert("Error!");}

);

fileDetails メソッド特定のバージョンのファイルの詳細を取得できる要求を生成します。署名

forcetk.Client.prototype.fileDetails = function(fileId, version, callback, error)

パラメータ

説明名前

既存のファイルの ID。null の場合、エラーが返されます。sfdcId

取得するバージョン。null の場合、最新バージョンを取得します。version

サーバ応答を非同期で受信して処理する関数。callback

サーバエラーを処理する関数。error

例ftkclient.fileDetails(id, null,

function(response){/* do something with the returned JSON data */

},

437

ハイブリッドアプリケーションの Files メソッドリファレンス

function(error){ alert("Error!");});

batchFileDetails メソッド複数のファイルの詳細を返します。署名

forcetk.Client.prototype.batchFileDetails =function(fileIds, callback, error)

パラメータ

説明名前

1 つ以上の既存のファイルの ID のリスト。リストの ID がひとつでも null の場合、エラーが返されます。

fileIds

サーバ応答を非同期で受信して処理する関数。callback

サーバエラーを処理する関数。error

例ftkclient.batchFileDetails(ids,

function(response){/* do something with the returned JSON data */

},function(error){ alert("Error!");}

);

fileRenditionPath メソッドservice/data を基準とするファイル変換の相対パスを返します。HTML (img タグなど) では、代わりにベアラートークン URL を使用します。署名

forcetk.Client.prototype.fileRenditionPath =function(fileId, version, renditionType, page)

パラメータ

説明名前

表示される既存のファイルの ID。null の場合、エラーが返されます。fileId

取得するバージョン。null の場合、最新バージョンを取得します。version

返される変換の種別を指定します。使用できる値は次のとおりです。renditionType

• PDF

438

ハイブリッドアプリケーションの Files メソッドリファレンス

説明名前

• FLASH

• SLIDE

• THUMB120BY90

• THUMB240BY180

• THUMB720BY480

null の場合、THUMB120BY90 が使用されます。

取得するページの開始値 0 のインデックス。null の場合、最初のページを取得します。

page

例ftkclient.fileRenditionPath(id, null, "THUMB240BY180", null);

fileContentsPath メソッドservice/dataを基準とするファイルコンテンツの相対パスを返します。html (imgタグなど) では、代わりにベアラートークン URL を使用します。署名

forcetk.Client.prototype.fileContentsPath =function(fileId, version)

パラメータ

説明名前

表示される既存のファイルの ID。null の場合、エラーが返されます。fileId

取得するバージョン。null の場合、最新バージョンを取得します。version

例ftkclient.fileContentsPath(id, null);

fileShares メソッドこのファイルを共有するエンティティのリストからページを返します。署名

forcetk.Client.prototype.fileShares =function(fileId, page, callback, error)

439

ハイブリッドアプリケーションの Files メソッドリファレンス

パラメータ

説明名前

表示される既存のファイルの ID。null の場合、エラーが返されます。fileId

取得する結果のページの開始値 0 のインデックス。null の場合、最初のページを取得します。

page

サーバ応答を非同期で受信して処理する関数。callback

サーバエラーを処理する関数。error

例ftkclient.fileShares(id, null,

function(response){/* do something with the returned JSON data */

},function(error){ alert("Error!");}

);

addFileShare メソッド指定されたファイル ID のファイル共有を指定されたエンティティ ID に追加します。署名

forcetk.Client.prototype.addFileShare =function(fileId, entityId, shareType, callback, error)

パラメータ

説明名前

共有される既存のファイルの ID。null の場合、IllegalArgumentException

が発生します。fileId

ファイルを共有する既存のユーザまたはグループの ID。null の場合、IllegalArgumentException が発生します。

entityID

共有種別。有効な値は「V」(表示) と「C」(コラボレーション) です。shareType

サーバ応答を非同期で受信して処理する関数。callback

サーバエラーを処理する関数。error

例ftkclient.addFileShare(id, null, "V",

function(response){

440

ハイブリッドアプリケーションの Files メソッドリファレンス

/* do something with the returned JSON data */},function(error){ alert("Error!");}

);

deleteFileShare メソッド指定されたファイル共有を削除します。署名

forcetk.Client.prototype.deleteFileShare =function(sharedId, callback, error)

パラメータ

説明名前

削除される既存のファイル共有の ID。null の場合、IllegalArgumentException が発生します。

shareId

サーバ応答を非同期で受信して処理する関数。callback

サーバエラーを処理する関数。error

例ftkclient.deleteFileShare(id,

function(response){/* do something with the returned JSON data */

},function(error){ alert("Error!");}

);

forceios パラメータ

forceios コマンドをパラメータ化する場合のいくつかの追加情報を次に示します。

説明パラメータ名

次のいずれかになります。--apptype

• 「native」(Objective-C 言語を使用するネイティブアプリケーション)

• 「native_swift」(Swift 言語を使用するネイティブアプリケーション)

441

forceios パラメータリファレンス

説明パラメータ名

• 「react_native」(Facebook の React Native フレームワークを使用するハイブリッドローカルアプリケーション)

• 「hybrid_remote」(VisualForce を使用するサーバ側ハイブリッドアプリケーション)

• 「hybrid_local」(VisualForce を使用しないクライアント側ハイブリッドアプリケーション)

アプリケーションの名前。--appname

会社の一意の識別子。この値とアプリケーション名が連結されて、アプリケーションを App Store に公開する

--companyid

ための一意のアプリケーション識別子が作成されます。たとえば、「com.myCompany.apps」のようになります。

会社の正式名称。たとえば、「Acme Widgets, Inc.」などです。

--organization

(ハイブリッドリモートアプリケーションのみ) リモート開始ページへのサーバパス。たとえば、/apex/MyAppStartPageのように入力します。

--startpage

(省略可能) プロジェクトを作成するフォルダ。フォルダが存在していない場合は、スクリプトで作成されます。デフォルトは現在の作業ディレクトリです。

--outputdir

(省略可能) 接続アプリケーションのコンシューマ鍵。デフォルトはサンプルアプリケーションのコンシューマ鍵です。

--appid

メモ: ここで値を指定しない場合は、App Store に公開する前に値を変更する必要があります。

(省略可能) 接続アプリケーションのコールバック URL。デフォルトはサンプルアプリケーションのコールバック URL です。

--callbackuri

メモ:

• ここで値を指定しない場合は、App Store に公開する前に値を変更する必要があります。

442

forceios パラメータリファレンス

説明パラメータ名

• --appidのデフォルト値を受け入れる場合、--callbackuriのデフォルト値も受け入れてください。

forcedroid パラメータ

forcedroid コマンドをパラメータ化する場合のいくつかの追加情報を次に示します。

説明パラメータ名

次のいずれかになります。--apptype

• 「native」• 「react_native」(Facebook の React Native フレームワー

クを使用するハイブリッドローカルアプリケーション)

• 「hybrid_remote」(VisualForce を使用するサーバ側ハイブリッドアプリケーション)

• 「hybrid_local」(VisualForce を使用しないクライアント側ハイブリッドアプリケーション)

アプリケーションの名前。--appname

プロジェクトを作成するフォルダ。既存の空でないフォルダを指定する必要があります。

--targetdir

アプリケーションのパッケージ識別子(「com.acme.app」など)。

--packagename

(ハイブリッドリモートアプリケーションのみ) Apex の開始ページへのサーバパス。たとえば、/apex/MyAppStartPageのように入力します。

--apexpage

(省略可能) オフラインデータにSmartStore、および必要に応じて SmartSync を使用する場合にのみ含めます。

--usesmartstore=yes

指定されていない場合、デフォルトの「NO」に設定されます。

443

forcedroid パラメータリファレンス