Comments
Description
Transcript
Salesforce Mobile SDK 開発ガイド
Version 31.0: Spring ’14 Salesforce Mobile SDK 開発ガイド Salesforce.com モバイル開発 最終更新日: 2014/9/5 © Copyright 2000–2014 salesforce.com, inc. All rights reserved. Salesforce.com およびその他の名称や商標は、salesforce.com, inc. の 登録商標です。本ドキュメントに記載されたその他の商標は、各社に所有権があります。 目次 目次 第 1 章: モバイル開発の概要...............................................................................................................1 対象利用者...............................................................................................................................................................................2 Salesforce1 Platform の使用とカスタムアプリケーションの作成の違い..........................................................................2 ネイティブ、HTML5、およびハイブリッド開発について.............................................................................................3 クイックスタート...................................................................................................................................................................6 開発の前提条件.......................................................................................................................................................................6 Force.com のサインアップ.........................................................................................................................................7 Mobile SDK を最新に保つ.....................................................................................................................................................7 このリリースの新機能...............................................................................................................................................7 第 2 章: Mobile SDK のインストール..................................................................................................8 Mobile SDK npm パッケージ.................................................................................................................................................9 最初の作業: Node.js および npm をインストールする...........................................................................................9 iOS のインストール....................................................................................................................................................9 Android のインストール...........................................................................................................................................10 Mobile SDK npm パッケージのアンインストール...............................................................................................11 Mobile SDK GitHub リポジトリ.........................................................................................................................................12 第 3 章: 接続アプリケーションの作成...............................................................................................13 接続アプリケーションを作成する.....................................................................................................................................14 第 4 章: Mobile SDK サンプルアプリケーション...............................................................................17 サンプルアプリケーションのインストール......................................................................................................................18 Android 用のサンプルアプリケーションのインストール...................................................................................18 Android サンプルアプリケーション...........................................................................................................19 iOS 用のサンプルアプリケーションのインストール..........................................................................................20 iOS サンプルアプリケーション..................................................................................................................20 第 5 章: ネイティブ iOS の開発.........................................................................................................22 iOS ネイティブクイックスタート......................................................................................................................................23 ネイティブ iOS の要件........................................................................................................................................................23 iOS プロジェクトの作成......................................................................................................................................................23 Xcode プロジェクトのテンプレートアプリケーションの実行...........................................................................26 ネイティブ iOS アプリケーションの開発.........................................................................................................................26 ログインとパスコードについて.............................................................................................................................26 メモリ管理について.................................................................................................................................................27 アプリケーションフローの概要.............................................................................................................................27 AppDelegate クラス...................................................................................................................................................27 ビューコントローラについて.................................................................................................................................29 RootViewController クラス.......................................................................................................................................29 i 目次 Salesforce REST API について.................................................................................................................................31 サポートされている操作.............................................................................................................................32 SFRestAPI インターフェース......................................................................................................................34 SFRestDelegate プロトコル..........................................................................................................................35 REST 要求の作成..........................................................................................................................................36 REST 要求の送信..........................................................................................................................................36 SFRestRequest クラス....................................................................................................................................37 SFRestRequest メソッドの使用....................................................................................................................37 SFRestAPI (Blocks) カテゴリ........................................................................................................................39 SFRestAPI (QueryBuilder) カテゴリ............................................................................................................39 SFRestAPI (Files) カテゴリ...........................................................................................................................41 チュートリアル: ネイティブ iOS Warehouse アプリケーションの作成........................................................................43 ネイティブ iOS アプリケーションを作成する.....................................................................................................44 ステップ 1: 接続アプリケーションを作成する.........................................................................................44 ステップ 2: ネイティブ iOS プロジェクトを作成する.............................................................................45 ステップ 3: 新しい iOS アプリケーションを実行する.............................................................................46 ステップ 4: iOS アプリケーションの仕組みを探索する..........................................................................47 リスト画面をカスタマイズする.............................................................................................................................49 ステップ 1: ルートビューコントローラを変更する.................................................................................50 ステップ 2: アプリケーションのルートビューを作成する ....................................................................50 ステップ 3: アプリケーションを試す.........................................................................................................51 詳細画面を作成する.................................................................................................................................................51 ステップ 1: アプリケーションの詳細ビューコントローラを作成する..................................................52 ステップ 2: DetailViewController を設定する.............................................................................................54 ステップ 3: 指定のイニシャライザを作成する.........................................................................................56 ステップ 4: ビューコントローラ間の通信を確立する.............................................................................58 ステップ 5: アプリケーションを試す.........................................................................................................64 iOS ネイティブサンプルアプリケーション......................................................................................................................64 第 6 章: ネイティブ Android の開発...................................................................................................66 Android ネイティブクイックスタート...............................................................................................................................67 ネイティブ Android の要件.................................................................................................................................................67 Android プロジェクトの作成...............................................................................................................................................67 Eclipse でのサンプルプロジェクトの設定.........................................................................................................................71 Android プロジェクトファイル...............................................................................................................................71 ネイティブ Android アプリケーションの開発..................................................................................................................71 create_native スクリプト...........................................................................................................................................71 Android アプリケーションの構造...........................................................................................................................72 ネイティブ API パッケージ....................................................................................................................................74 ネイティブクラスの概要.........................................................................................................................................75 SalesforceSDKManager クラス......................................................................................................................75 ii 目次 KeyInterface インターフェース....................................................................................................................76 AccountWatcher クラス.................................................................................................................................77 PasscodeManager クラス................................................................................................................................77 Encryptor クラス............................................................................................................................................78 SalesforceActivity クラス、SalesforceListActivity クラス、および SalesforceExpandableListActivity クラス.......................................................................................................................................................78 UI クラス........................................................................................................................................................79 ClientManager クラス....................................................................................................................................79 RestClient クラス...........................................................................................................................................79 RestRequest クラス........................................................................................................................................80 FileRequests クラス........................................................................................................................................81 WrappedRestRequest クラス.........................................................................................................................83 LoginActivity クラス......................................................................................................................................83 その他の UI クラス.......................................................................................................................................83 UpgradeManager クラス................................................................................................................................83 ユーティリティクラス.................................................................................................................................84 ForcePlugin クラス.........................................................................................................................................84 パスコードの使用.....................................................................................................................................................84 リソースの処理.........................................................................................................................................................85 REST API の使用......................................................................................................................................................88 Android テンプレートアプリケーション: 詳細.....................................................................................................91 TemplateApp クラス......................................................................................................................................91 MainActivity クラス.......................................................................................................................................92 TemplateApp マニフェスト..........................................................................................................................93 チュートリアル: ネイティブ Android Warehouse アプリケーションの作成.................................................................94 前提条件.....................................................................................................................................................................94 ネイティブ Android アプリケーションを作成する..............................................................................................95 ステップ 1: 接続アプリケーションを作成する.........................................................................................95 ステップ 2: ネイティブ Android プロジェクトを作成する......................................................................96 ステップ 3: 新しい Android アプリケーションを実行する......................................................................97 ステップ 4: Android アプリケーションの仕組みを探索する...................................................................97 リスト画面をカスタマイズする.............................................................................................................................99 ステップ 1: 既存のコントロールを削除する.............................................................................................99 ステップ 2: SOQL クエリを更新する........................................................................................................99 ステップ 3: アプリケーションを試す.......................................................................................................101 詳細画面を作成する...............................................................................................................................................102 ステップ 1: 詳細画面を作成する...............................................................................................................102 ステップ 2: DetailActivity クラスを作成する...........................................................................................104 ステップ 3: DetailActivity クラスをカスタマイズする...........................................................................104 ステップ 4: 2 つのアクティビティをリンクする - 第 1 部: データクラスを作成する.......................105 iii 目次 ステップ 5: 2 つのアクティビティをリンクする - 第 2 部: リスト項目クリックハンドラを実装 する.........................................................................................................................................................106 ステップ 6: [更新] ボタンを実装する.......................................................................................................108 ステップ 7: アプリケーションを試す.......................................................................................................110 Android ネイティブサンプルアプリケーション.............................................................................................................110 第 7 章: ハイブリッド開発の概要.....................................................................................................111 ハイブリッド開発について...............................................................................................................................................112 iOS のハイブリッド開発....................................................................................................................................................112 iOS ハイブリッドサンプルアプリケーション....................................................................................................112 Android のハイブリッド開発.............................................................................................................................................113 Android ハイブリッドサンプルアプリケーション.............................................................................................113 ハイブリッドアプリケーションの JavaScript ファイル..................................................................................................114 バージョン設定および JavaScript ライブラリの互換性..................................................................................................115 ハイブリッドアプリケーションでのセッション管理....................................................................................................116 例: 適切な JavaScript ライブラリの提供...........................................................................................................................119 第 8 章: HTML5 開発.......................................................................................................................121 HTML5 の開発要件...........................................................................................................................................................122 Visualforce を使用した HTML5 コンテンツの配信........................................................................................................122 Salesforce データへのアクセス: コントローラと API.....................................................................................................122 第 9 章: ファイルとネットワーキング.............................................................................................125 アーキテクチャ...................................................................................................................................................................126 ファイルのダウンロードと共有の管理............................................................................................................................126 ファイルのアップロード...................................................................................................................................................127 暗号化とキャッシュ...........................................................................................................................................................127 Android アプリケーションでのファイルの使用.............................................................................................................127 要求キューの管理...................................................................................................................................................128 iOS ネイティブアプリケーションでのファイルの使用................................................................................................129 要求の管理...............................................................................................................................................................129 ハイブリッドアプリケーションでのファイルの使用....................................................................................................130 第 10 章: SmartSync を使用した Salesforce オブジェクトへのアクセス............................................132 Backbone テクノロジについて..........................................................................................................................................133 モデルとモデルコレクション...........................................................................................................................................133 モデル.......................................................................................................................................................................133 モデルコレクション...............................................................................................................................................135 JavaScript での SmartSync Data Framework の使用...........................................................................................................136 オフラインキャッシュ.......................................................................................................................................................137 オフラインキャッシュの実装...............................................................................................................................139 オフラインキャッシュのための StoreCache の使用...........................................................................................140 iv 目次 競合検出...............................................................................................................................................................................143 ミニチュートリアル: 競合検出.............................................................................................................................146 カスタム API エンドポイントへのアクセス...................................................................................................................147 Force.RemoteObject クラス.....................................................................................................................................147 Force.RemoteObjectCollection クラス....................................................................................................................148 Apex REST リソースの使用..................................................................................................................................150 外部オブジェクトの使用 (ベータ)........................................................................................................................153 チュートリアル: SmartSync アプリケーションの作成...................................................................................................154 プロジェクトの設定...............................................................................................................................................155 アプリケーションの HTML ファイルの編集.....................................................................................................155 SmartSync モデルおよびコレクションの作成.....................................................................................................158 テンプレートの作成...............................................................................................................................................159 検索ビューの追加...................................................................................................................................................160 検索結果リストビューの追加...............................................................................................................................161 検索結果リスト項目ビューの追加........................................................................................................................162 ルータ.......................................................................................................................................................................164 SmartSync サンプルアプリケーション.............................................................................................................................167 User and Group Search のサンプル.........................................................................................................................170 User Search のサンプル...........................................................................................................................................172 Account Editor のサンプル.....................................................................................................................................175 第 11 章: オフラインでのデータの安全な保存.................................................................................184 SmartStore について............................................................................................................................................................185 SmartStore のスープ................................................................................................................................................185 SmartStore のデータ型............................................................................................................................................186 日付表現.......................................................................................................................................................186 ハイブリッドアプリケーションでの SmartStore の有効化............................................................................................186 既存の Android アプリケーションへの SmartStore の追加............................................................................................187 スープの登録.......................................................................................................................................................................187 スープからのデータの取得...............................................................................................................................................189 スマート SQL クエリ.........................................................................................................................................................192 カーソルの使用...................................................................................................................................................................193 データの操作.......................................................................................................................................................................194 擬似 SmartStore の使用.......................................................................................................................................................196 NativeSqlAggregator サンプルアプリケーション: ネイティブアプリケーションでの SmartStore の使用................198 第 12 章: 転送通知と Mobile SDK....................................................................................................201 転送通知について...............................................................................................................................................................202 Android での転送通知の使用.............................................................................................................................................202 GCM (Android) 用に接続アプリケーションを設定する....................................................................................203 コードの変更 (Android)..........................................................................................................................................203 v 目次 iOS での転送通知の使用....................................................................................................................................................204 APNS (iOS) 用に接続アプリケーションを設定する..........................................................................................205 コードの変更 (iOS).................................................................................................................................................206 第 13 章: モバイルアプリケーションでの認証、セキュリティ、ID................................................208 OAuth の用語......................................................................................................................................................................209 OAuth2 認証フロー............................................................................................................................................................209 OAuth 2.0 ユーザエージェントフロー.................................................................................................................210 OAuth 2.0 更新トークンフロー.............................................................................................................................211 範囲パラメータの値...............................................................................................................................................212 ID URL の使用........................................................................................................................................................213 カスタムログインサーバの設定............................................................................................................................218 OAuth トークンの取り消し...................................................................................................................................218 Android ネイティブアプリケーションでの更新トークンの取り消し処理......................................................219 トークンの取り消しイベント....................................................................................................................219 トークンの取り消し: パッシブ処理..........................................................................................................220 トークンの取り消し: アクティブ処理......................................................................................................220 接続アプリケーション.......................................................................................................................................................221 PIN セキュリティについて...................................................................................................................................221 OAuth 2.0 サイトおよび Force.com サイトを使用したポータル認証...........................................................................222 第 14 章: Mobile SDK アプリケーションでの Communities の使用.................................................224 コミュニティと Mobile SDK アプリケーション.............................................................................................................225 「API の有効化」プロファイルを設定する....................................................................................................................225 権限セットを設定する.......................................................................................................................................................226 API アクセス権をユーザに付与する................................................................................................................................227 ログインエンドポイントを設定する...............................................................................................................................227 コミュニティのブランド設定...........................................................................................................................................228 コミュニティログインのカスタマイズ............................................................................................................................229 コミュニティでの外部認証の使用...................................................................................................................................231 外部認証プロバイダについて...............................................................................................................................232 コミュニティ URL パラメータの使用.................................................................................................................233 Scope パラメータの使用.........................................................................................................................................233 Facebook 認証プロバイダの設定...........................................................................................................................235 Salesforce 認証プロバイダの設定...........................................................................................................................237 OpenID Connect 認証プロバイダの設定..............................................................................................................239 例: Mobile SDK アプリケーションからアクセスできるようにコミュニティを設定する.........................................242 プロファイルに権限を追加する............................................................................................................................242 コミュニティを作成する.......................................................................................................................................243 コミュニティに API ユーザプロファイルを追加する.......................................................................................243 新しい取引先責任者およびユーザを作成する....................................................................................................243 vi 目次 新しいコミュニティログインをテストする........................................................................................................244 例: Facebook 認証できるようにコミュニティを設定する..............................................................................................245 Facebook アプリケーションを作成する...............................................................................................................245 Salesforce 認証プロバイダを定義する...................................................................................................................246 Facebook アプリケーションを設定する...............................................................................................................247 認証プロバイダの Apex クラスをカスタマイズする..........................................................................................247 Salesforce コミュニティを設定する.......................................................................................................................248 第 15 章: Mobile SDK でのマルチユーザのサポート........................................................................250 マルチユーザのサポートについて...................................................................................................................................251 マルチユーザのサポートの実装.......................................................................................................................................251 Android ネイティブ API.........................................................................................................................................252 UserAccount クラス.....................................................................................................................................254 UserAccountManager クラス.......................................................................................................................256 AccountSwitcherActivity クラス..................................................................................................................256 UserSwitchReceiver クラス..........................................................................................................................257 iOS ネイティブ API................................................................................................................................................258 SFUserAccount クラス.................................................................................................................................258 SFUserAccountManager クラス..................................................................................................................260 ハイブリッド API...................................................................................................................................................262 第 16 章: 以前のリリースからの移行...............................................................................................264 Mobile SDK Android アプリケーションを 2.1 から 2.2 に移行する.............................................................................265 Mobile SDK iOS アプリケーションを 2.1 から 2.2 に移行する....................................................................................265 iOS ハイブリッドアプリケーション....................................................................................................................265 Mobile SDK ライブラリパッケージを更新する......................................................................................266 SalesforceSecurity ヘッダーファイルの検索パスを追加する..................................................................266 ハイブリッドローカルアイテムを更新する............................................................................................266 AppDelegate 実装を更新する.....................................................................................................................266 iOS ネイティブアプリケーション........................................................................................................................267 Mobile SDK ライブラリパッケージを更新する......................................................................................267 SalesforceSecurity ヘッダーファイルの検索パスを追加する..................................................................267 パスコード関連のコードを新しい SalesforceSecurity クラスに移行する..............................................268 AppDelegate 実装を更新する.....................................................................................................................268 以前のリリースからの移行...............................................................................................................................................268 バージョン 2.0 からバージョン 2.1 への移行......................................................................................................269 Mobile SDK Android アプリケーションを 2.0 から 2.1 に移行する......................................................269 Mobile SDK iOS アプリケーションを 2.0 から 2.1 に移行する.............................................................269 バージョン 1.5 からバージョン 2.0 への移行......................................................................................................272 Mobile SDK Android アプリケーションを 1.5 から 2.0 に移行する......................................................272 Mobile SDK iOS アプリケーションを 1.5 から 2.0 に移行する.............................................................275 vii 目次 第 17 章: リファレンス.....................................................................................................................279 REST API リソース............................................................................................................................................................280 iOS アーキテクチャ...........................................................................................................................................................281 ネイティブ iOS オブジェクト...............................................................................................................................281 Android アーキテクチャ....................................................................................................................................................283 Android パッケージおよびクラス.........................................................................................................................283 ライブラリ...............................................................................................................................................................289 Android リソース....................................................................................................................................................289 Files API リファレンス.......................................................................................................................................................293 FileRequests メソッド (Android).............................................................................................................................293 SFRestAPI (Files) カテゴリ — 要求メソッド (iOS).............................................................................................299 ハイブリッドアプリケーションの Files メソッド..............................................................................................306 viii 第1章 モバイル開発の概要 トピック: • • • • • • 対象利用者 Salesforce1 Platform の使用とカス タムアプリケーションの作成の違 い ネイティブ、HTML5、およびハ イブリッド開発について クイックスタート 開発の前提条件 Mobile SDK を最新に保つ Salesforce Mobile SDK では、Force.com の機能を利用して、Salesforce データにアクセスして操作するスタンドアロンモバイルアプリケーショ ンを作成できます。 Force.comが、簡単でわかりやすく、非常に生産的なクラウドコンピュー ティング用のプラットフォームだということは、デスクトップ上で実 証されています。開発者は、Web インターフェースのポイントアンド クリックツールを使用して、アプリケーションコンポーネント(カス タムオブジェクトや項目、ワークフロールール、Visualforce ページ、 Apex クラスおよびトリガなど)を定義することができ、そのコンポー ネントを組み合わせて、優れたアプリケーションを作り出すことがで きます。 Mobile SDK は、以下を提供することで Force.com クラウドアーキテク チャを Android および iOS アプリケーションに統合します。 • JavaScript を介して Salesforce データにアクセスして同期する SmartSync Data Framework • Salesforce 接続アプリケーションポリシーの実装 • 永続化機能や更新機能を含む、OAuth ログイン情報管理 • Salesforce REST API のラッパー • ハイブリッドアプリケーション用の Cordova ベースのコンテナ • ハイブリッドアプリケーションのデータ同期 • SmartStore を使用した安全なオフラインストレージ • ネイティブアプリケーションの転送通知のサポート • Salesforce Communities のサポート • 複数ユーザログインのサポート 1 モバイル開発の概要 対象利用者 対象利用者 Salesforce Mobile SDK を使用すれば、熟練のモバイル開発者だけにとどまらず誰でもモバイルアプリケーション を開発できます。 このガイドは、OAuth2 や REST API などのモバイル技術に関する知識がすでにあり、Force.com に関してある程 度の経験を持つ開発者を主に対象としています。ただし、必ずしもこれに該当しなくても心配は不要です。この ガイドは、幅広い利用者が使用できるようになっています。たとえば、組織をサポートするために新しいモバイ ルアプリケーションを開発する Salesforce システム管理者や Force.com の使用経験がないモバイル開発者も利用で きます。このいずれかに該当していれば、内容を理解するうえで問題はありません。 モバイルデバイスのユーザ設定を行う管理者の場合は、『Salesforce Mobile Implementation Guide』を参照してく ださい。 Salesforce1 Platform の使用とカスタムアプリケーションの作成 の違い Salesforce モバイルユーザ用の機能を開発する場合には、2 つのオプションがあります。このマニュアルでは、 Mobile SDK 開発のみを取り上げていますが、Salesforce にはモバイルアプリケーション開発用に Salesforce1 Platform も用意されています。 Salesforce1 の拡張と Mobile SDK を使用したカスタムアプリケーションの作成には違いがいくつかあります。 Salesforce1 についての詳細は、developer.salesforce.com/docs を参照してください。 Salesforce1 Platform • • • • • • • • • 定義されたユーザインターフェースがある。 Salesforce データにフルアクセスできる。 Salesforce1 Platform で開発された機能と統合された環境を作成できる。 パブリッシャーアクションにより、独自のアプリケーション/機能を含める方法が提供される。 ポイント & クリックまたはプログラムによるカスタマイズを使用して、Salesforce1 をカスタマイズできる。 Visualforce ページまたは Force.com Canva アプリケーションを使用して、プログラムにより機能を追加できる。 Salesforce1 のカスタマイズまたはアプリケーションは、Salesforce1 ナビゲーションに準拠する。このため、た とえば Visualforce ページなどをナビゲーションメニューまたはパブリッシャーからコールできます。 既存の Salesforce 開発手法 (ポイント & クリックおよびプログラムの両方) を活用できる。 すべての Salesforce エディションに含まれ、salesforce.com でサポートされている。 カスタムアプリケーション カスタムアプリケーションは、Salesforce Mobile SDK で作成する独立型アプリケーションの場合と、プレーン HTML5 および JQuery Mobile/Ajax を使用するブラウザアプリケーションの場合があります。カスタムアプリケー ションでは、次のことができます。 • • カスタムユーザ環境を定義する。 ネイティブおよびハイブリッドのローカルアプリケーションで REST API を使用するか、JavaScript Remoting を使用するハイブリッドアプリケーションで Visualforce を使用して、Salesforce データにアクセスする。HTML5 アプリケーションでは、JQueryMobile および Ajax を使用して同じ操作を行います。 2 モバイル開発の概要 • • • • • • • ネイティブ、HTML5、およびハイブリッド開発につい て 顧客向け公開用のユーザインターフェースをブランド設定する。 Java for Android または Objective-C for iOS を使用するネイティブ API を使用するか、JavaScript および HTML5 を使用するハイブリッドコンテナを使用して、スタンドアロンモバイルアプリケーションを作成する (Mobile SDK のみ)。 Apple App Store や Google Play などのモバイル業界チャネルを使用して、アプリケーションを配布する (Mobile SDK のみ)。 複雑なオフライン動作を設定および制御する (Mobile SDK のみ)。 転送通知を使用する (Winter '14 の開発者プレビュー: Mobile SDK ネイティブアプリケーションでのみ使用可 能)。 独自の OAuth モジュールを使用して、カスタムセキュリティコンテナを設計する (Mobile SDK のみ)。 Mobile SDK のその他の重要な考慮事項: ◊ オープンソース SDK は、npm インストーラおよび GitHub から無料でダウンロードできます。ライセンス は必要ありません。 ◊ アプリケーションを外部開発環境 (iOS の場合は Xcode、Android の場合は Eclipse またはそれに類似するも の) で開発およびコンパイルする必要があります。 ◊ 開発費用は 0 ~ 100万ドルまたはそれ以上で、さらにメンテナンス費用がかかります。 ネイティブ、HTML5、およびハイブリッド開発について Salesforce Mobile SDK では、アプリケーションの開発方法を選択できます。選択できるオプションは、開発スキ ル、デバイスおよびテクノロジの要件、目的、スケジュールによって変わります。 Mobile SDK では、3 通りの方法でモバイルアプリケーションを作成できます。 • ネイティブアプリケーションは、特定のモバイルプラットフォーム (iOS または Android) に固有であり、それ ぞれのプラットフォームでサポートする開発ツールと言語 (iOS の Xcode と Objective-C、Android の Eclipse と Java など) を使用します。ネイティブアプリケーションは、外観とパフォーマンスは最高ですが、最も多く の開発作業を必要とします。 • HTML5 アプリケーションでは、標準の Web テクノロジ (通常、HTML5、JavaScript および CSS) を使用し、 モバイル Web ブラウザを通してアプリケーションを提供します。この「Write Once, Run Anywhere (一度書け ば、どこでも実行できる)」というモバイル開発へのアプローチでは、複数のデバイスで動作するクロスプラッ トフォームのモバイルアプリケーションが作成されます。開発者は、HTML5 と JavaScript のみを使用して高 度なアプリケーションを作成することもできますが、セッション管理、安全なオフラインストレージ、ネイ ティブデバイス機能 (カメラ、カレンダー、通知など) へのアクセスなど、いくつかの難題も残ります。 • ハイブリッドアプリケーションは、Salesforce コンテナ内の Web アプリケーションをラップすることにより、 HTML5 Web アプリケーションの開発の容易さをネイティブプラットフォームの機能と結合します。この結 合手法では、デバイスのネイティブ機能を利用でき App Store から提供できるアプリケーションが作成されま す。また、Salesforce ハイブリッドコンテナを通して提供される Visualforce ページを使用して、ハイブリッド アプリケーションを作成することもできます。 3 モバイル開発の概要 ネイティブ、HTML5、およびハイブリッド開発につい て ネイティブアプリケーション ネイティブアプリケーションは、使い勝手、機能、全体的なモバイルの操作性の点において最良です。ネイティ ブアプリケーションでしか実現できないことがいくつかあります。 • • • • 高速グラフィック API — ネイティブプラットフォームでは最も高速なグラフィックを実現できます。限られ た要素のみを含む静的画面を表示する場合には重要でないかもしれませんが、大量のデータを使用し、かつ すばやい更新を必要とする場合には効果的です。 流動的なアニメーション — 高速グラフィック API と関連し、流動的なアニメーションを実現する機能です。 これは、ゲーム、非常にインタラクティブなレポート、写真や音を変換する強度の演算アルゴリズムには特 に重要です。 組み込みコンポーネント — カメラ、アドレスブック、地理位置情報、およびデバイスに対してネイティブな その他の機能を、モバイルアプリケーションにシームレスに統合できます。他の重要な組み込みコンポーネ ントとして、暗号化されたストレージもありますが、これについては後で説明します。 使いやすさ — ユーザはネイティブプラットフォームを使い慣れています。この使い慣れた操作感をユーザが 期待するネイティブ機能に追加することで、アプリケーションがさらに使いやすくなります。 ネイティブアプリケーションの開発には通常、統合開発環境 (IDE) を使用します。IDE には、作成、デバッグ、 プロジェクト管理、バージョン設定用のツール、およびプロの開発者が必要とする他のツールが備えられていま す。ネイティブアプリケーションの開発はさらに難しいため、これらのツールが必要です。同様に、他の開発シ ナリオに比べてより高い経験レベルが要求されます。プロの開発者は、実証済みの API やフレームワーク、定義 済みコンポーネントを使用した簡単な特殊効果、すべてのコードを 1 箇所にまとめることの利点に必ずしも価値 を見出しません。 HTML5 アプリケーション HTML5 モバイルアプリケーションは、基本的には小さいモバイルデバイス画面で動作するように設計された単 一または一連の Web ページです。HTML5 アプリケーション自体はデバイスにとらわれず、最新のどのモバイ ルブラウザでも開くことができます。コンテンツは Web に存在するため検索可能であり、特定のタイプのアプ リケーション (ショッピングなど) では大きな利点となります。 Web アプリケーションの技術的な障壁は低いため、モバイル開発を初めて行う場合は、ネイティブ開発やハイブ リッド開発に比べて着手しやすいといえます。ただし、すべてのモバイルデバイスは、使用可能な画面サイズお 4 モバイル開発の概要 ネイティブ、HTML5、およびハイブリッド開発につい て よび解像度が独自のアイデアに基づいて構成されています。この多様性により、異なるデバイスをテストする場 合の負担が大きくなります。たとえば、ブラウザの非互換性は、Android デバイスで特に目立ちます。 「Write Once, Run Anywhere」という HTML5 手法の重要な点は、配布とサポートがネイティブアプリケーショ ンに比べて非常に簡単に行えるということです。バグ修正または機能の追加が必要な場合でも、すべてのユーザ に対して行われ、導入されます。ネイティブアプリケーションでは開発期間とテスト期間が長くなります。通常 コンシューマは、その期間を経た後にストアにログインして新バージョンをダウンロードし、最新の修正を取得 する必要があります。 HTML5 アプリケーションは、開発とサポートが簡単であり、最も広範囲にわたるデバイスを使用できますが、 次のような欠点もあります。 • • • • 安全なオフラインストレージ — HTML5 ブラウザでは、オフラインのデータベースとキャッシュをサポート していますが、標準の暗号化はサポートされません。Mobile SDK ネイティブアプリケーションでは、3 つの 機能をすべて使用できます。 セキュリティ — 一般に、ネイティブプラットフォームで単純なセキュリティ対策を実装する場合でも、モバ イル Web 開発者にとっては複雑な作業となることがあります。また、ユーザにとっても不便な場合がありま す。たとえば、認証を必要とする Web アプリケーションでは、アプリケーションを再起動するたび、または バックグラウンド状態から戻るたびに、ユーザはログイン情報を入力する必要があります。 ネイティブ機能 — カメラ、アドレスブック、その他のネイティブ機能は、アクセスが可能であっても、ブラ ウザのプラットフォームが制限されます。 ネイティブのデザイン — HTML5 はネイティブの外観しかエミュレートできず、顧客は使い慣れた複合操作 を使用できません。 ハイブリッドアプリケーション ハイブリッドアプリケーションは、ネイティブプラットフォーム機能へのアクセスを提供するシンコンテナ内で ラップされた HTML5 および JavaScript を使用して作成されます。ハイブリッドアプリケーションのほとんどの 部分では、両方のアプリケーションの最良の特性が提供されます。つまり、開発は HTML5 アプリケーションと ほぼ同じくらい簡単で、ネイティブアプリケーションのすべての機能が提供されます。また、ハイブリッドアプ リケーションでは、JavaScript で SmartSync Data Framework を使用して、次の操作を行うことができます。 • • • Salesforce データをモデル化、クエリ、検索、編集する オフラインで使用できるように Salesforce データを安全にキャッシュする ローカルにキャッシュされたデータを Salesforce サーバと同期する ネイティブアプリケーションはデバイスにインストールされますが、HTML5 アプリケーションは Web サーバ に存在するため、ハイブリッドアプリケーションのファイルがデバイスとサーバのどちらに保存されるのか疑問 に思われるかも知れません。 ハイブリッドアプリケーションは、ローカルまたはリモートで実装できます。 ローカル HTML と JavaScript のコードは、ネイティブアプリケーションと同様の構造で、モバイルアプリケーション バイナリ内でパッケージ化できます。この場合、REST API および Ajax を使用して、デバイスとクラウド 間でデータを移動します。 リモート 完全な Web アプリケーションをサーバから実装することもできます (パフォーマンス向上のためオプショ ンとしてキャッシュもできます)。コンテナアプリケーションは、完全なアプリケーションをサーバから取 得し、それをブラウザウィンドウに表示します。 このガイドでは、両方のタイプのハイブリッド開発について説明します。 5 モバイル開発の概要 クイックスタート ネイティブ、HTML5、およびハイブリッドのまとめ 次の表に、3 つのモバイル開発シナリオの比較の概要を示します。 ネイティブ HTML5 ハイブリッド グラフィック ネイティブ API HTML、キャンバス、 SVG HTML、キャンバス、SVG パフォーマンス 最速 高速 高速 デザイン ネイティブ エミュレート エミュレート 配布 App Store Web App Store カメラ はい ブラウザに依存 はい 通知 はい いいえ はい 連絡先、カレンダー はい いいえ はい オフラインストレージ 安全なファイルシステ 安全ではない、共有 ム SQL、キー - 値ストア 安全なファイルシステム、共 有 SQL 地理位置情報 はい はい はい スワイプ はい はい はい ピンチ、スプレッド はい はい はい 接続 オンライン、オフライ ほぼオンライン ン 開発手段 Objective C、Java オンライン、オフライン HTML5、CSS、JavaScript HTML5、CSS、JavaScript クイックスタート 詳細を後で確認したいという方のために、ネイティブ開発シナリオごとに「クイックスタート」トピックを用意 しています。 • iOS ネイティブクイックスタート • Android ネイティブクイックスタート 開発の前提条件 ある程度の予備知識の習得やシステム設定を経験してから Mobile SDK アプリケーションの作成を始めることを お勧めします。 Force.com に関するある程度の経験があると役立ちます。Force.com Developer Edition 組織が必要です。 Mobile SDK アプリケーションの設計やデバッグを行うには、OAuth、ログインおよびパスコードフロー、Salesforce 接続アプリケーションについて熟知している必要があります。「モバイルアプリケーションでの認証、セキュリ ティ、ID」を参照してください。 次の要件は、特定のプラットフォームおよびテクノロジに適用されます。 6 モバイル開発の概要 Force.com のサインアップ • iOS アプリケーション (ハイブリッドまたはネイティブ) の作成方法については、「ネイティブ iOS の要件」 を参照してください。 • Android アプリケーション (ハイブリッドまたはネイティブ) の作成方法については、「ネイティブ Android の 要件」を参照してください。 • リモートハイブリッドアプリケーションを作成するには、Visualforce を持つ組織が必要です。 Force.com のサインアップ すべての Salesforce 開発者プログラムの豊富なチュートリアル、ブログ、およびサポートフォーラムにアクセス するには、Force.com に参加します。 1. ブラウザで developer.force.com/join にアクセスします。 2. 各項目にユーザ情報と会社情報を入力します。 3. [Email Address (メールアドレス)] 項目には、Web ブラウザから簡単に確認できる公開アドレスを使用し てください。 4. 一意の [Username (ユーザ名)] を入力します。ユーザ名もメールアドレスの形式にする必要がありますが、 メールアドレスと同じにする必要はなく、通常は違うものを入力することをお勧めします。ユーザ名は developer.force.com でのログイン情報および ID であるため、担当する作業を説明するユーザ名 ([email protected]) や自分自身を表すユーザ名 ([email protected]) を選ぶことで、より有 益に使用できます。 5. [Master Subscription Agreement (マスターサブスクリプション契約)] を読み、チェックボックスをオン にします。 6. 表示された画像認証文字列を入力し、[Submit Registration (登録を実行)] をクリックします。 7. その後まもなく、ログインリンクを記載したメールが届きます。リンクをクリックし、パスワードを変更し ます。 Mobile SDK を最新に保つ Mobile SDK は急速に進化しているため、公開フォーラムを定期的にチェックしてください。 次に、最も重要なリソースへのリンクを示します。 • 最新リリースは、NPM レジストリまたは Mobile SDK GitHub リポジトリからいつでも入手できます。 • 新機能を取得して最新の状態に更新してください。 • 最新の記事、ブログの投稿、チュートリアル、Web セミナーは、http://www2.developerforce.com/mobile/resources にあります。 • http://boards.developerforce.com/t5/Mobile/bd-p/mobile で、メッセージボードの会話に参加してください。 このリリースの新機能 新機能および更新された機能の最新のお知らせについては、Force.com wiki を参照してください。 現在の Salesforce Mobile SDK リリースの新機能と以前のリリースの履歴を確認するには、「Mobile SDK Release Notes」を参照してください。 7 第2章 Mobile SDK のインストール トピック: • • Mobile SDK npm パッケージ Mobile SDK GitHub リポジトリ Salesforce Mobile SDK には、2 つのインストールパスがあります。 • (推奨) Node Packaged Module (npm) スクリプトを使用して、用意さ れた開発設定に SDK をインストールできます。 • Mobile SDK オープンソースコードを GitHub からダウンロードし、 独自の開発環境を設定できます。 8 Mobile SDK のインストール Mobile SDK npm パッケージ Mobile SDK npm パッケージ モバイル開発者のほとんどは、Mobile SDK を「ブラックボックス」として使用することで、できるだけ早くア プリケーションの作成を開始することができます。そのため、Salesforce には、iOS 用の forceios と、Android 用 の forcedroid という 2 つの npm パッケージが用意されています。 Mobile SDK npm パッケージには、SDK リリースの静的スナップショットが含まれています。iOS の npm パッ ケージでは、未コンパイルのソースコードではなくバイナリモジュールがインストールされます。Android の npm パッケージでは、バイナリではなく SDK ソースコードのスナップショットがインストールされます。npm スクリプトでは、Mobile SDK をインストールするだけでなく、新しいテンプレートプロジェクトを作成して SDK サンプルをインストールすることもできます。 Salesforce Mobile SDK 用の npm パッケージは、https://www.npmjs.org にあります。 メモ: npm パッケージではソース制御がサポートされないため、新しいリリース用にインストールを動 的に更新することはできません。代わりに、リリースごとに別個にインストールします。新しいバージョ ンの SDK にアップグレードするには、npmjs.org の Web サイトにアクセスして、新しいパッケージをダ ウンロードしてください。 最初の作業: Node.js および npm をインストールする Mobile SDK npm インストーラを使用するには、Node.js をインストールします。Node.js インストーラにより、 npm が自動的にインストールされます。 1. www.nodejs.org/download から 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 をインス トールしてください。 1. コマンドプロンプトで、forceios パッケージを使用して、Mobile SDK をグローバル (推奨) またはローカルで インストールします。 a. グローバルインストールの場合: sudo コマンドを使用して、「グローバル」オプション -g を追加します。 sudo npm install forceios -g 9 Mobile SDK のインストール Android のインストール -g オプションでは、npm install を任意のディレクトリから実行できます。npm ユーティリティにより パッケージが /usr/local/lib/node_modules にインストールされ、/usr/local/bin のバイナリモ ジュールにリンクされます。大部分のユーザは /usr/local の「参照・更新」権限がないため、sudo オ プションが必要になります。 b. ローカルインストールの場合: ディレクトリを目的のインストールフォルダに変更して、sudo や –g のな い npm コマンドを使用します。 npm install forceios このコマンドにより、現在のフォルダの下にある node_modules フォルダに Salesforce Mobile SDK がイン ストールされます。バイナリモジュールは、./node_modules/.bin/ でリンクされます。このシナリオで は、すでに「参照・更新」権限のあるローカルフォルダにインストールすることが多いため、sudo を使 用することはほとんどありません。 Android のインストール 最も迅速で簡単にAndroid 開発をはじめるには、forcedroid npm パッケージを使用して Salesforce Mobile SDK をイ ンストールしてください。 1. forcedroid パッケージを使用して Mobile SDK をグローバル (推奨) またはローカルにインストールします。 a. グローバルインストールの場合: コマンドの最後に「グローバル」オプション -g を追加します。 Windows 以外の環境の場合、sudo コマンドを使用します。 sudo npm install forcedroid -g Windows の場合: npm install forcedroid -g -g オプションを使用して、任意のディレクトリから npm install を実行します。Windows 以外の環境の 場合、npm ユーティリティにより、/usr/local/lib/node_modules にパッケージがインストールさ れ、/usr/local/bin でバイナリモジュールがリンクされます。大部分のユーザは /usr/local の「参 照・更新」権限がないため、sudo オプションが必要になります。 Windows 環境の場 合、%APPDATA%\npm\node_modules にグローバルパッケージがインストールされ、%APPDATA%\npm でバ イナリがリンクされます。 b. ローカルインストールの場合: ディレクトリを目的のインストールフォルダに変更して、sudo や –g オプ ションのない npm コマンドを使用します。 npm install forcedroid このコマンドにより、Salesforce Mobile SDK が現在のディレクトリの下にある node_modules ディレクト リにインストールされます。バイナリモジュールは、./node_modules/.bin/ でリンクされます。 この シナリオでは、すでに「参照・更新」権限のあるローカルフォルダにインストールすることが多いため、 sudo を使用することはほとんどありません。 10 Mobile SDK のインストール Mobile SDK npm パッケージのアンインストール 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 $ ローカルでインストールしたパッケージをアンインストールするには、パッケージをインストールしたフォルダ から uninstall コマンドを実行します。次に例を示します。 $ pwd /Users/joeuser cd <my_projects/my_sdk_folder> npm uninstall forceios 11 Mobile SDK のインストール Mobile SDK GitHub リポジトリ 誤ったディレクトリからローカルインストールをアンインストールしようとすると、次のようなエラーメッセー ジが表示されます。 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 を使用すれば、公開されたプレリリースの開 発環境でソースコードを監視できます。この場合、iOS と Android の両方のアプリケーションに、アプリケー ションと共に構築される SDK ソースコードが含まれます。 Mobile SDK にアクセスするために GitHub にサインアップする必要はありませんが、このソーシャルコーディン グコミュニティに参加することをお勧めします。https://github.com/forcedotcom 最新の Mobile SDK リリースは、次の公開リポジトリからいつでも入手できます。 • • https://github.com/forcedotcom/SalesforceMobileSDK-iOS https://github.com/forcedotcom/SalesforceMobileSDK-Android iOS: Mobile SDK GitHub リポジトリのコピー (省略可能) 1. OS X ターミナルアプリケーションで git clone git://github.com/forcedotcom/SalesforceMobileSDK-iOS.git コマンドを発行して、Mobile SDK 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 を実行します。 Android: Mobile SDK GitHub リポジトリのコピー (省略可能) 1. ブラウザで、Mobile SDK Android GitHub リポジトリ https://github.com/forcedotcom/SalesforceMobileSDK-Android に移動します。 2. git clone git://github.com/forcedotcom/SalesforceMobileSDK-Android.git コマンドを使用して、 リポジトリをローカルファイルシステムにコピーします。 3. コピーしたリポジトリがインストールされたディレクトリでコマンドプロンプトを開き、コマンドライン ./install.sh からインストールスクリプトを実行します。 メモ: Windows ユーザの場合: cscript install.vbs を実行します。 12 第3章 接続アプリケーションの作成 トピック: • 接続アプリケーションを作成する モバイルアプリケーションから Salesforce サービスに接続できるように するには、接続アプリケーションを作成する必要があります。接続ア プリケーションには、このガイドのすべての開発シナリオの前提条件 となるコンシューマ鍵が含まれます。 13 接続アプリケーションの作成 接続アプリケーションを作成する 接続アプリケーションを作成する 接続アプリケーションを作成するには、Salesforce アプリケーションを使用します。 1. Force.com インスタンスにログインします。 2. [設定] で、[作成] > [アプリケーション] に移動します。 3. [接続アプリケーション] で、[新規] をクリックします。 4. 「基本情報」の手順を実行します。 5. 「API (OAuth 設定の有効化)」の手順を実行します。 6. [保存] をクリックします。 メモ: • OAuth に提供される [コールバック URL] は有効な URL である必要はありません。アプリケーション でこの項目に予期されるものと一致しているだけで十分です。「sfdc://」など、任意のカスタムプ レフィックスを使用できます。 • 接続アプリケーションの詳細ページに、コンシューマ鍵が表示されます。このキーは後で必要になる ため、コピーしておくことをお勧めします。 • 新しい接続アプリケーションを作成したら、トークンが伝搬されるまで数分待ってから、アプリケー ションを実行します。 「範囲パラメータの値」も参照してください。 基本情報 このセクションでは、アプリケーション名、ロゴ、連絡先情報など、アプリケーションに関する基本情報を指定 します。 1. [接続アプリケーション名] を入力します。この名前が接続アプリケーションのリストに表示されます。 メモ: 現在の接続アプリケーションの名前は、組織内で一意にする必要があります。接続アプリケー ションが Spring '14 以降のリリースを使用して作成された場合は、削除済み接続アプリケーションの 名前を再使用できるようになりました。接続アプリケーションが Spring '14 より前のリリースを使用 して作成された場合は、削除済み接続アプリケーションの名前は再使用できません。 2. プログラムからアプリケーションを参照するときに使用する [API 参照名] を入力します。API 参照名は、デ フォルトの空白を除いた名前になります。使用できるのは、文字、数字、アンダースコアのみであるため、 元のアプリケーション名に他の記号などが含まれている場合は、デフォルトの名前を編集する必要がありま す。 3. salesforce.com からアプリケーション提供者またはそのサポートチームへの連絡に使用する [取引先責任者 メー ル] を入力します。このアドレスは、アプリケーションをインストールするシステム管理者には提供されませ ん。 4. salesforce.com から連絡する必要がある場合に使用する [取引先責任者 電話] を入力します。この番号は、アプ リケーションをインストールするシステム管理者には提供されません。 5. 接続アプリケーションのリストや、認証時にユーザに表示される同意ページにロゴを表示するには、[ロゴ画 像 URL] を入力します。URL には HTTPS を使用する必要があります。ロゴは、高さ 125 ピクセル以下、幅 14 接続アプリケーションの作成 接続アプリケーションを作成する 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 です。 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 サービスへのアクセスを許可します。 15 接続アプリケーションの作成 接続アプリケーションを作成する 一意の識別子へのアクセスを許可 (openid) ログインユーザの OpenID Connect アプリケーションの一意の識別子へのアクセスを許可します。 フルアクセス (full) ログインユーザがアクセスできるすべてのデータへのアクセスを許可します。full は更新トークンを返 しません。更新トークンを取得するには、refresh_token の範囲を明示的に要求する必要があります。 ユーザに代わっていつでも要求を実行 (refresh_token、offline_access) 更新トークンを受信できる場合に、それを返すように指定します。これにより、ユーザがオフラインの ときにアプリケーションがユーザのデータを操作できます。refresh_token 範囲は、offline_access と同じです。 カスタムアプリケーションへのアクセスの提供 (visualforce) Visualforce ページへのアクセスを許可します。 Web 経由のデータへのアクセスを提供 (web) Web で access_token を使用することを許可します。これには visualforce も含まれ、Visualforce ペー ジへのアクセスが許可されます。 Spring '12 リリースより前に、組織でリモートアクセスに対して [この組織のユーザにはユーザ承認は必要ありませ ん] オプションが選択されていた場合、アプリケーションが作成された組織と同じ組織のユーザは、引き続きア プリケーションで自動的に承認されます。参照のみの [この組織のユーザにはユーザ承認は必要ありません] チェッ クボックスがオンで表示されている場合は、この状態であることを示します。接続アプリケーションの場合、ア プリケーションを作成したら、システム管理者がアプリケーションをインストールし、[許可されているユーザ] を [管理者が承認したユーザ] に設定することをお勧めします。当初リモートアクセスオプションがオフだった場 合、チェックボックスは表示されません。 16 第4章 Mobile SDK サンプルアプリケーション トピック: • サンプルアプリケーションのイン ストール Salesforce Mobile SDK には、主要な機能を示す豊富なサンプルアプリ ケーションが含まれています。iOS および Android 用のハイブリッド サンプルとネイティブサンプルは、独自のアプリケーションの基盤と して使用したり、参考のために検討したりできます。 17 Mobile SDK サンプルアプリケーション サンプルアプリケーションのインストール サンプルアプリケーションのインストール GitHub では、サンプルアプリケーションは対象プラットフォームの Mobile SDK リポジトリに存在します。サン プルアプリケーションに直接アクセスすることも、npm コマンドを使用してインストールすることもできます。 GitHub からのサンプルへのアクセス Mobile SDK を GitHub から直接コピーすると、すべてのサンプルファイルが正しい場所に配置されます。次に、 SalesforceSDK プロジェクト、SmartStore プロジェクト、サンプルプロジェクトを Eclipse ワークスペースに 含めることによって、Android サンプルを作成できます。iOS の場合は、リポジトリのコピー後に、リポジトリ ルートフォルダで ./install.sh を必ず実行してください。iOS サンプルプロジェクトを実行するには、 SalesforceMobileSDK-iOS/SalesforceMobileSDK.xcworkspace を開きます。 Android 用のサンプルアプリケーションのインストール npm を使用して SDK をインストールした場合は、forcedroid コマンドラインユーティリティを使用してサンプル アプリケーションをインストールします。次のいずれかの操作が可能です。 • forcedroid アプリケーションのプロンプトで、対象ディレクトリを対話形式で設定する。 • コマンドラインで対象ディレクトリを直接指定する。 対話形式での対象ディレクトリの指定 対象ディレクトリを対話形式で入力するには、次のいずれかの操作を実行します。 • Mobile SDK をグローバルにインストールした場合は、「forcedroid samples」と入力する。 • Mobile SDK をローカルにインストールした場合は、「<forcedroid_path>/node_modules/.bin/ forcedroid samples」と入力する。 forcedroid ユーティリティから、対象ディレクトリ名を入力するよう求められます。 18 Mobile SDK サンプルアプリケーション Android サンプルアプリケーション メモ: 最適な結果を得るには、まだ存在していない対象ディレクトリを指定します。対象ディレクトリが 存在しないと、forcedroid により作成されます。対象ディレクトリが存在してもサンプルディレクトリが 含まれていない場合は、forcedroid によりサンプルがインストールされます。対象ディレクトリが存在 し、すでに 1 つ以上のサンプルディレクトリが含まれている場合は、既存のディレクトリが検出された 時点で forcedroid が終了し、残りのサンプルはインストールされません。 Android サンプルアプリケーション ネイティブ RestExplorer: SalesforceSDK の OAuth および REST API 機能を示します。また、REST API アクションを Honeycomb タブレットから調べる場合にも便利です。 1. Eclipse ワークスペースからアプリケーションを実行するには、[RestExplorer] プロジェクトを右クリックし、 [Run As (別のユーザとして実行)] > [Android Application (Android アプリケーション)] を選択します。 2. テストを実行するには、[RestExplorerTest] プロジェクトを右クリックし、[Run As (別のユーザとして実行)] > [Android JUnit Test (Android JUnit テスト)] を選択します。 NativeSqlAggregator: SQL と SmartSQL の統合を示します。また、そのようなアプリケーションとして SmartStore のネイティブ実装の方法も示します。Eclipse ワークスペースからアプリケーションを実行するには、 [NativeSqlAggregator] プロジェクトを右クリックし、[Run As (別のユーザとして実行)] > [Android Application (Android アプリケーション)] を選択します。 FileExplorer: Files API および基盤となる Google Volley のネットワーキングの機能強化を示します。Eclipse ワー クスペースからアプリケーションを実行するには、[FileExplorer] プロジェクトを右クリックし、[Run As (別の ユーザとして実行)] > [Android Application (Android アプリケーション)] を選択します。 ハイブリッド • • • • • • • • AccountEditor: SmartSync Data Framework を使用して Salesforce データにアクセスする方法について説明しま す。 SampleApps/HybridFileExplorer: Files API を示します。 SampleApps/ContactExplorer: ContactExplorer サンプルアプリケーションでは、PhoneGap (Cordova とも呼 ばれる) を使用して、ローカルデバイスの取引先責任者を取得します。また、forcetk.mobilesdk.js ツー ルキットを使用して、Salesforce REST API で REST トランザクションを実装します。アプリケーションでは、 Salesforce SDK の OAuth2 サポートを使用して OAuth ログイン情報を取得し、JavasScript イベントを送信する ことによって、そのログイン情報を forcetk.mobilesdk.js に伝搬します。 SampleApps/test/ContactExplorerTest: ContactExplorer サンプルアプリケーションをテストします。 SampleApps/VFConnector: ネイティブコンテナ内の Visualforce ページのラップ方法を示す VFConnector サン プルアプリケーションです。この例では、BasicVFTest という Visualforce ページが組織に存在することを想 定しています。アプリケーションではまず、Salesforce SDK OAuth2 サポートを使用して OAuth のログイン情 報を取得し、そのログイン情報を使用して、Visualforce ページにアクセスするための適切な Web ビュー Cookie を設定します。 SampleApps/test/VFConnectorTest: VFConnector サンプルアプリケーションをテストします。 SampleApps/SmartStoreExplorer: SmartStore API を探索できます。 SampleApps/test/SmartStoreExplorerTest: SmartStoreExplorer サンプルアプリケーションをテストします。 19 Mobile SDK サンプルアプリケーション iOS 用のサンプルアプリケーションのインストール iOS 用のサンプルアプリケーションのインストール npm を使用して SDK をインストールした場合は、forceios コマンドラインユーティリティを使用してサンプルア プリケーションをインストールします。次のいずれかの操作が可能です。 • forceios アプリケーションのプロンプトで、対象ディレクトリを対話形式で設定する。 • コマンドラインで対象ディレクトリを直接指定する。 対話形式での対象ディレクトリの指定 対象ディレクトリを対話形式で入力するには、次のいずれかの操作を実行します。 • Mobile SDK をグローバルにインストールした場合は、「forceios samples」と入力する。 • Mobile SDK をローカルにインストールした場合は、「<forceios_path>/node_modules/.bin/ forceios samples」と入力する。 forceios ユーティリティから、対象ディレクトリ名を入力するよう求められます。 メモ: 最適な結果を得るには、まだ存在していない対象ディレクトリを指定します。対象ディレクトリが 存在しないと、forceios により作成されます。対象ディレクトリが存在してもサンプルディレクトリが含 まれていない場合は、forceios によりサンプルがインストールされます。対象ディレクトリが存在し、す でに 1 つ以上のサンプルディレクトリが含まれている場合は、既存のサンプルディレクトリが検出され た時点で forceios が終了し、サンプルはインストールされません。 iOS サンプルアプリケーション ネイティブ • RestAPIExplorer では、ネイティブのすべての REST API ラッパーが実行されます。これは、 native/SampleApps/RestAPIExplorer の Mobile SDK for iOS にあります。 • NativeSqlAggregator には、SQL の集約例と、ネイティブ SmartStore の実装が表示されます。このサンプルア プリケーションは、native/SampleApps/NativeSqlAggregator の SDK for iOS にあります。 20 Mobile SDK サンプルアプリケーション • iOS サンプルアプリケーション FileExplorer には、Files API と、その基盤となる MKNetwork ネットワーク機能強化が示されます このサンプ ルアプリケーションは、native/SampleApps/FileExplorer の SDK for iOS にあります。 ハイブリッド • • • • • AccountEditor: SmartSync Data Framework を使用して Salesforce データにアクセスする方法について説明しま す。 HybridFileExplorer: Files API を示します。 ContactExplorer: ContactExplorer サンプルアプリケーションでは、PhoneGap (Cordova とも呼ばれる) を使 用して、ローカルデバイスの取引先責任者を取得します。また、forcetk.mobilesdk.js ツールキットを使 用して、Salesforce REST API で REST トランザクションを実装します。アプリケーションでは、Salesforce SDK の OAuth2 サポートを使用して OAuth ログイン情報を取得し、JavaScript イベントを送信することによっ て、そのログイン情報を forcetk.mobilesdk.js に伝搬します。 VFConnector: ネイティブコンテナ内の Visualforce ページのラップ方法を示す VFConnector サンプルアプリ ケーションです。この例では、BasicVFTest という Visualforce ページが組織に存在することを想定していま す。アプリケーションではまず、Salesforce SDK OAuth2 サポートを使用して OAuth のログイン情報を取得 し、そのログイン情報を使用して、Visualforce ページにアクセスするための適切な Web ビュー Cookie を設定 します。 SmartStoreExplorer: SmartStore API を探索できます。 21 第5章 ネイティブ iOS の開発 トピック: • • • • • • iOS ネイティブクイックスタート ネイティブ iOS の要件 iOS プロジェクトの作成 ネイティブ iOS アプリケーション の開発 チュートリアル: ネイティブ iOS Warehouse アプリケーションの作 成 iOS ネイティブサンプルアプリ ケーション Salesforce Mobile SDK では、iOS でモバイルアプリケーションを開発 するためのライブラリとサンプル Xcode プロジェクトが提供されます。 iOS ネイティブ SDK では、次の 2 つの主要な機能が提供されます。 • OAuth2 ログインプロセスの自動化。これにより、OAuth をアプリ ケーションに統合しやすくなります。 • REST API へのアクセス。アクセスをできるかぎり簡略化するすべ てのインフラストラクチャクラス (RestKit などのサードパーティの ライブラリを含む) が使用されます。 forceios アプリケーションを使用してネイティブアプリケーションを作 成すると、完全に機能するネイティブサンプルアプリケーションとし てプロジェクトが開始します。この単純なアプリケーションでは、 Salesforce 組織に接続し、簡単なクエリを実行できます。多くの操作は できませんが、設計どおりに動作することを確認できます。 22 ネイティブ iOS の開発 iOS ネイティブクイックスタート iOS ネイティブクイックスタート すばやく開始する手順は、次のとおりです。 1. ネイティブ iOS 要件をすべて満たしていることを確認します。 2. Mobile SDK for iOS をインストールします。必要に応じて、代わりに GitHub から Mobile SDK for iOS をイン ストールすることもできます。 3. テンプレートアプリケーションを実行します。 ネイティブ iOS の要件 Mobile SDK 2.2 を使用した iOS の開発には、次のソフトウェアが必要です。 • Xcode — バージョン 5.0 以降 (最新バージョンを推奨)。 • iOS 6.0 以降。 • Mac OS X 10.8 (「Mountain Lion」) 以降。 Salesforce 側には、以下も必要です。 • Salesforce Mobile SDK 2.2 for iOS。「iOS のインストール」を参照してください。 • 接続アプリケーションが存在する Salesforce Developer Edition 組織。 iOS プロジェクトの作成 新しいアプリケーションを作成するには、コマンドラインで forceios を再度使用します。アプリケーションを設 定する方法は 2 つあります。 • forceios アプリケーションからプロンプトが表示されたときに、アプリケーションオプションを対話形式で設 定します。 • 直接コマンドラインでアプリケーションオプションを指定する。 対話形式でのアプリケーションオプションの指定 対話形式でアプリケーションオプションを入力するには、次のいずれかを実行します。 • Mobile SDK をグローバルにインストールした場合は、「forceios create」と入力する。 • Mobile SDK をローカルにインストールした場合は、「<forceios_path>/node_modules/.bin/forceios create」と入力する。 設定値ごとに、forceios ユーティリティによってプロンプトが表示されます。 23 ネイティブ iOS の開発 iOS プロジェクトの作成 アプリケーションオプションの直接指定 forceios の完全なコマンド文字列を入力して、設定を直接指定することもできます。使用方法に関する情報を表 示するには、引数を指定せずに「forceios」と入力します。次のように使用可能なオプションのリストが表示 されます。 $ forceios Usage: forceios create --apptype=<Application Type> (native, hybrid_remote, hybrid_local) --appname=<Application Name> --companyid=<Company Identifier> (com.myCompany.myApp) --organization=<Organization Name> (Your company's/organization's name) --startpage=<App Start Page> (The start page of your remote app. Only required for hybrid_remote) [--outputdir=<Output directory> (Defaults to the current working directory)] [--appid=<Salesforce App Identifier> (The Consumer Key for your app. Defaults to the sample app.)] [--callbackuri=<Salesforce App Callback URL (The Callback URL for your app. Defaults to the sample app.)] この情報を使用して、「forceios create」の後にオプションと値を続けて入力します。次に例を示します。 $ forceios create --apptype="native" --appname="package-test" --companyid="com.acme.mobile_apps" --organization="Acme Widgets, Inc." --outputdir="PackageTest" --packagename="com.test.my_new_app" XCode での新規プロジェクトの実行 forceios テンプレートを使用して作成されたアプリケーションは、「標準で」実行準備が整っています。アプリ ケーションの作成スクリプトが完了したら、プロジェクトを Xcode で開いて実行できます。 1. Xcode で [File (ファイル)] > [Open (開く)] を選択します。 2. 指定した出力フォルダに移動します。 3. アプリケーションの xcodeproj ファイルを開きます。 4. 左上隅にある [Run (実行)] ボタンをクリックすると、処理中の新しいアプリケーションが表示されます。 forceios コマンドパラメータ forceios コマンドパラメータの説明を次に示します。 パラメータ名 説明 --apptype 次のいずれかになります。 • 24 「native」 ネイティブ iOS の開発 iOS プロジェクトの作成 パラメータ名 説明 • 「hybrid_remote」(VisualForce を使用するサーバ側ハ イブリッドアプリケーション) • 「hybrid_local」(VisualForce を使用しないクライアン ト側ハイブリッドアプリケーション) --appname アプリケーションの名前 --companyid 会社の一意の識別子。この値とアプリケーション名が 連結されて、アプリケーションを App Store に公開する ための一意のアプリケーション識別子が作成されます。 たとえば、「com.myCompany.apps」のようになりま す。 --organization 会社の正式名称。たとえば、「Acme Widgets, Inc.」な どです。 --packagename アプリケーションのパッケージ識別子。たとえば、 「com.acme.app」などです。 --startpage (ハイブリッドリモートアプリケーションのみ) リモー ト開始ページへのサーバパス。 たとえ ば、/apex/MyAppStartPage のように入力します。 --outputdir (省略可能) プロジェクトを作成するフォルダ。フォル ダが存在していない場合は、スクリプトで作成されま す。デフォルトは現在の作業ディレクトリです。 --appid (省略可能) 接続アプリケーションのコンシューマ鍵。 デフォルトはサンプルアプリケーションのコンシュー マ鍵です。 メモ: ここで値を指定しない場合は、App Store に公開する前に値を変更する必要があります。 (省略可能) 接続アプリケーションのコールバック URL。 デフォルトはサンプルアプリケーションのコールバッ ク URL です。 --callbackuri メモ: • • ここで値を指定しない場合は、App Store に 公開する前に値を変更する必要があります。 --appid のデフォルト値を受け入れる場合、 --callbackuri のデフォルト値も受け入れ てください。 (省略可能) オフラインデータに SmartStore を使用する 場合にのみ含めます。指定されていない場合、デフォ ルトの false に設定されます。 --usesmartstore=true 25 ネイティブ iOS の開発 Xcode プロジェクトのテンプレートアプリケーションの 実行 Xcode プロジェクトのテンプレートアプリケーションの実行 Xcode プロジェクトのテンプレートには、すぐに実行できるサンプルアプリケーションが含まれています。 1. [Command-R] キーを押すと、デフォルトのテンプレートアプリケーションが iOS シミュレータで実行されま す。 2. アプリケーションは、起動時に OAuth 認証フローで開始し、認証ページが表示されます。ログイン情報を入 力し、[Login (ログイン)] をクリックします。 3. 許可を求められたら、[Allow (許可)] をタップします。 これで、サンプルプロジェクトをコンパイルし、実行できるようになりました。これは、OAuth2 を介して組織 にログインし、select Name from Account SOQL クエリを発行し、結果を UITableView インスタンスに表示 する簡単なアプリケーションです。 ネイティブ 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 では、ログイン画面とパスコード画面の表示、および認証ハンドシェ イクの処理が行われます。これらの画面を表示するために、アプリケーションで何らかの操作をする必要はあり ません。ただし、ログインフローおよび OAuth トークンの処理方法を理解しておく必要はあります。「PIN セ キュリティについて」および「OAuth2 認証フロー」を参照してください。 26 ネイティブ iOS の開発 メモリ管理について メモリ管理について Mobile SDK 2.0 以降では、ネイティブ iOS アプリケーションで Automatic Reference Counting (ARC) を使用して、 オブジェクトメモリが管理されます。オブジェクトを割り当てたあとに、割り当て解除することを覚えておく必 要はありません。ARC の構文、ガイドライン、ベストプラクティスについては、「Mac Developer Library」 の 「Mac Developer Library」を参照してください。 アプリケーションフローの概要 forceios アプリケーションを使用してプロジェクトを作成すると、新しいアプリケーションで AppDelegate、 InitialViewController、および RootViewController という 3 つのクラスが定義されます。AppDelegate オブジェクトでは、最初に表示するビューとして InitialViewController が読み込まれます。認証プロセスが 完了すると、AppDelegate オブジェクトにより、RootViewController に関連付けられたビューがアプリケー ションのエントリポイントとして表示されます。 テンプレートアプリケーションで示すワークフローは一例にすぎません。AppDelegate およびサポートクラス をカスタマイズして、目的のワークフローにすることができます。REST API コールを使用したデータの取得、 データの表示、他のビューの起動、サービスの実行などを行うことができます。アプリケーションは、ユーザが アプリケーションを終了するか、デバイスが再起動されるまでメモリ内でアクティブのままになります。 Mobile SDK を使用して構築されたネイティブ iOS アプリケーションは、他の iOS アプリケーションと同じ設計 になります。main.m のソースファイルでは、アプリケーションの残りの部分のルートオブジェクトとなる UIApplicationMain オブジェクトが作成されます。UIApplicationMain コンストラクタでは、アプリケーショ ンのライフサイクルを管理する AppDelegate オブジェクトが作成されます。 AppDelegate クラス AppDelegate クラスは、iOS アプリケーションの実際のエントリポイントです。Mobile SDK アプリケーション では、AppDelegate によって標準の iOS UIApplicationDelegate インターフェースが実装されます。ネイティ 27 ネイティブ iOS の開発 AppDelegate クラス ブ iOS アプリケーションを作成するための Mobile SDK テンプレートアプリケーションでは、Salesforce 固有の起 動時のほとんどの機能が実装されます。 AppDelegate テンプレートをカスタマイズするには、Force.com 接続アプリケーションの情報を次の静的変数に 入力します。 • RemoteAccessConsumerKey static NSString * const RemoteAccessConsumerKey = @"3MVG9Iu66FKeHhINkB1l7xt7kR8...YFDUpqRWcoQ2.dBv_a1Dyu5xa"; • OAuthRedirectURI static NSString * const OAuthRedirectURI = @"testsfdc:///mobilesdk/detect/oauth/done"; OAuth 機能は、独立したモジュールに保存されています。この分離によって、Salesforce 認証のオンデマンドで の使用が可能になります。ログインプロセスは、AppDelegate の実装内から開始することも、実際に必要にな るまで (サブビューから OAuth をコールするなど) 延期することもできます。 初期化 次に、AppDelegate でテンプレートアプリケーションが初期化される仕組みの概要を示します。ニーズに合わ せて、これらすべての詳細を変更できます。 1. [AppDelegate init] メッセージが実行されると、次の処理が行われます。 • • 接続アプリケーション識別子や OAuth 範囲など、設定項目が初期化される。 SFAuthenticationManager、logoutInitiated、および loginHostChanged の通知をリスンする通知 オブザーバーが追加される。 logoutInitiated 通知では、ユーザが自発的にログアウトするか、ログイン情報が無効であるために強 制的にログアウトされたときに、アプリケーションで対応できます。loginHostChanged 通知では、ユー ザがログインホストを (本番から Sandbox などに) 変更したときに、アプリケーションで対応できます。 サ ンプルアプリケーションにある logoutInitiated: および loginHostChanged: のハンドラメソッドを参 照してください。 • [SFAuthenticationManager loginWithCompletion:failure:] メッセージの認証の「success」および 「failure」ブロックが初期化される。 これらのブロックにより、認証プロセスの完了時の処理が決まりま す。 2. アプリケーションの起動時に、UIApplicationDelegate メソッドである application:didFinishLaunchingWithOptions: がコールされます。 テンプレートアプリケーションは、 このメソッドを使用して、UIWindow プロパティの初期化、初期ビューの表示 (initializeAppViewState を 参照)、認証の初期化を行います。認証に成功すると、SFAuthenticationManager で initialLoginSuccessBlock (「success」ブロック) が実行されます。 3. アプリケーションの RootViewController を作成および表示する setupRootViewController が、 initialLoginSuccessBlock からコールされます。 このプロセスのどの部分もカスタマイズできます。 少なくとも、認証後に独自のコントローラが表示されるよう に setupRootViewController を変更してください。 また、initializeAppViewState をカスタマイズして独 自の起動ページを表示したり、ニーズに合わせて InitialViewController をカスタマイズすることもできま す。 さらに、アプリケーションにとって最も適切な場所に認証の詳細を移動することもできます。 Mobile SDK 28 ネイティブ iOS の開発 ビューコントローラについて では、アクションの実行時期 (または実行するかどうか) は規定されませんが、標準の iOS 規則は適用されます。 たとえば、self.window には、application:didFinishLaunchingWithOptions: が完了するまでに rootViewController が必要です。 UIApplication イベントハンドラ アプリケーションの代理クラスを使用して、UIApplication イベントハンドラを実装することもできます。実 装またはカスタマイズを考慮すべき重要なイベントハンドラは、次のとおりです。 application:didFinishLaunchingWithOptions: アプリケーションの起動時の最初のエントリポイントです。プロセスが最初に開始したとき (バックグラウ ンド/フォアグラウンドサイクルの後ではない) にのみコールされます。 applicationDidBecomeActive アプリケーションがフォアグラウンドになるたびにコールされます。iOS SDK にはデフォルトの親動作は ありませんが、それを使用する場合は下から順に実装する必要があります。 すべての UIApplication イベントハンドラのリストは、「iOS Developer Library」の「UIApplicationDelegate Protocol Reference」を参照してください。 ビューコントローラについて 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 とやり取りするためのフレーム 29 ネイティブ iOS の開発 RootViewController クラス ワークを設定する SFRestDelegate プロトコルが実装されます。ルートビューコントローラの定義方法に関係な く、SFRestDelegate を使用して REST API 経由で Salesforce データにアクセスする場合は、SFRestDelegate を実装する必要があります。 RootViewController のデザイン Mobile SDK を使用して作成される非常に基本的なアプリケーションの要素として、RootViewController クラ スでは重要項目のみが取り扱われます。主要な 2 つのタスクは次のとおりです。 • • Salesforce REST API を使用して Salesforce データをクエリする Salesforce データをテーブルに表示する 以上の操作を行うため、このクラスは 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.com SFRestRequest *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: — 要求を処理できませんでした。代理オブジェクトはエラーメッセージ を受信します。 30 ネイティブ iOS の開発 Salesforce REST API について • requestDidCancelLoad — 管理者による操作、ネットワーク障害、他の予期しないイベントなど、外部要因 • により要求がキャンセルされました。代理オブジェクトは戻り値を受信しません。 requestDidTimeout — Salesforce サーバが時間内に応答しませんでした。代理オブジェクトは戻り値を受信 しません。 応答は、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 開発者ガイド』を参照してください。 31 ネイティブ iOS の開発 サポートされている操作 サポートされている操作 iOS REST API は、Salesforce REST および SOAP API で提供される標準のオブジェクト操作をサポートしていま す。Salesforce Mobile SDK には、その REST 要求 API の代理バージョンとブロックバージョンが備えられていま す。代理要求メソッドは SFRestAPI クラスで定義されますが、ブロック要求メソッドは SFRestAPI (Blocks) カテゴリで定義されます。ファイル要求は、SFRestAPI (Files) カテゴリで定義されます。「SFRestAPI (Files) カテゴリ」を参照してください。 サポートされる操作は次のとおりです。 操作 Manual REST request Delegate メソッド Block メソッド send:delegate: sendRESTRequest: failBlock: completeBlock: requestForQuery: performSOQLQuery: failBlock: completeBlock: requestForSearch: performSOSLSearch: failBlock: completeBlock: requestForMetadataWithObjectType: performMetadataWithObjectType: failBlock: completeBlock: requestForDescribeGlobal performDescribeGlobalWithFailBlock: completeBlock: requestForDescribeWithObjectType: performDescribeWithObjectType: failBlock: completeBlock: requestForRetrieveWithObjectType: performRetrieveWithObjectType: objectId: ユーザが作成した要 求を実行する SOQL query 特定の SOQL 文字列 を実行し、結果の データセットを返す SOSL search 特定の SOSL 文字列 を実行し、結果の データセットを返す Metadata オブジェクトのメタ データを返す Describe global 組織で使用できるす べてのオブジェクト とそのメタデータの リストを返します。 Describe with object type 1 つのオブジェクト 種別の説明を返しま す。 Retrieve 32 ネイティブ iOS の開発 操作 サポートされている操作 Delegate メソッド Block メソッド オブジェクト ID 別 に単一レコードを取 得する objectId: Update requestForUpdateWithObjectType: 指定された対応付け でオブジェクトを更 新します。 Upsert 外部 ID が外部 ID 項 目に現在存在してい fieldList: failBlock:completeBlock: fieldList: objectId: fields: requestForUpsertWithObjectType: externalIdField: externalId: 33 performUpdateWithObjectType: objectId: fields: failBlock: completeBlock: performUpsertWithObjectType: externalIdField: externalId: fields: failBlock: completeBlock: ネイティブ iOS の開発 操作 SFRestAPI インターフェース Delegate メソッド るかどうかに基づい て、外部データから オブジェクトを更新 または挿入します。 Create fields: requestForCreateWithObjectType: 指定したオブジェク トに新しいレコード を作成します。 Delete fields: requestForDeleteWithObjectType: 指定された ID を持 つ特定のタイプのオ ブジェクトを削除し ます。 Versions Block メソッド objectId: requestForVersions performCreateWithObjectType: fields: failBlock: completeBlock: performDeleteWithObjectType: objectId: failBlock: completeBlock: performRequestForVersionsWithFailBlock: Salesforce バージョン のメタデータを返し ます。 Resources completeBlock: requestForResources performRequestForResourcesWithFailBlock: リソース名および URI を含む、指定さ れた API バージョン で使用可能なリソー スを返します。 completeBlock: SFRestAPI インターフェース SFRestAPI は、Salesforce REST 要求を作成および書式設定するためのネイティブインターフェースを定義しま す。 これは、要求を書式設定し、Salesforce サービスに送信してから、SFRestDelegate プロトコルの実装エン トリに非同期応答をリレーすることによって動作します。 SFRestAPI は、SFRestRequest インスタンスのファクトリとしての役割を果たし、Salesforce REST API でサ ポートされる要求種別を表すメソッドグループを定義します。各 SFRestAPI メソッドは、1 つの要求種別に対応 します。各メソッドでは、要求が SFRestRequest インスタンス形式で返されます。その戻り値を使用して、要 求を Salesforce サーバに送信します。HTTP コーディングレイヤはカプセル化されるため、REST API 構文を考 慮する必要はありません。 サポートされるクエリファクトリメソッドのリストについては、「サポートされている操作」を参照してくださ い。 34 ネイティブ iOS の開発 SFRestDelegate プロトコル 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. } 35 ネイティブ iOS の開発 REST 要求の作成 応答を 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 には、構文に関する詳細のほとんどを処理するファクトリメソッドが備えられています。 Mobile SDK は、実行時に SFRestAPI の単一インスタンスを作成します。このインスタンスを使用して、 SFRestRequest オブジェクトを取得し、そのオブジェクトを Salesforce サーバに送信します。 REST 要求を SFRestAPI 代理オブジェクトから Salesforce サーバに送信する手順は、次のとおりです。 1. SOQL、SOSL、または他の REST の要求文字列を作成します。 36 ネイティブ iOS の開発 SFRestRequest クラス 標準の SOQL クエリおよび SOSL クエリの場合、最も便利で信頼できる方法は、SFRestAPI クラスのファク トリメソッドを使用することです。「サポートされている操作」を参照してください。 2. 要求文字列を使用して、SFRestRequest オブジェクトを作成します。 ニーズに合った要求ファクトリメソッドを使用して、SFRestAPI の単一インスタンスにメッセージを送信し ます。たとえば、次のコードでは、SOQL クエリを準備する SFRestAPI:requestForQuery: メソッドを使 用しています。 // Send a request factory message to the singleton SFRestAPI instance SFRestRequest *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 のインスタンスを作成します。 2. SFRestRequest オブジェクトで、必要なプロパティを設定します。 3. SFRestAPI の単一インスタンスで send:delegate: をコールし、作成した SFRestRequest オブジェクトを 最初のパラメータとして渡します。 37 ネイティブ iOS の開発 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 = [SFRestRequest requestWithMethod: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 = [SFRestRequest requestWithMethod:SFRestMethodPOST path:[NSString stringWithFormat: @"/v26.0/chatter/feeds/ record/%@/feed-items", recordId] queryParams: (NSDictionary *) [SFJsonUtils objectFromJSONString:body]]; [[SFRestAPI sharedInstance] send:request delegate:self]; 6. 要求の HTTP ヘッダーを設定するには、setHeaderValue:forHeaderName メソッドを使用します。このメ ソッドは、HTML 表示用に事前にエンコードされている Chatter フィードを表示する場合に役立ちます。ネ 38 ネイティブ iOS の開発 SFRestAPI (Blocks) カテゴリ イティブアプリケーションの Chatter コメントに不要なエスケープシーケンスが表示されている場合、要求を 送信する前に次のように X-Chatter-Entity-Encoding ヘッダーを「false」に設定します。 ... [request setHeaderValue:@"false" forHeaderName:@"X-Chatter-Entity-Encoding"]; [[SFRestAPI sharedInstance] send:request delegate:self]; 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 での匿名関数を 要求する条件と一致することがよくあります。ただし、これはあくまでも一般的な目安です。最終的には。アプ リケーションの実際の動作を調べたうえで判断する必要があります。 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 *)term fieldScope:(NSString *)fieldScope 39 ネイティブ iOS の開発 SFRestAPI (QueryBuilder) カテゴリ objectScope:(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 Fields RETURNING Widget__c (name Where createddate = THIS_FISCAL_QUARTER) この場合は、キーを “Widget__c” に設定し、値を “name WHERE createddate = “THIS_FISCAL_QUARTER” に設定します。次に例を示します。 [SFRestAPI SOSLSearchWithSearchTerm:@"all of these will be escaped:~{]" objectScope:[NSDictionary dictionaryWithObject:@"name WHERE createddate="THIS_FISCAL_QUARTER" forKey:@"Widget__c"]]; ◊ NSNull — 範囲が指定されていません。 • limit — 返される結果数を制限するには、このパラメータを、受信する結果の最大数に設定します。 SOQL メソッド SOQL 文字列を作成する SOQL QueryBuilder メソッドは、次のとおりです。 + (NSString *) SOQLQueryWithFields:(NSArray *)fields sObject:(NSString *)sObject where:(NSString *)where limit:(NSInteger)limit; + (NSString *) SOQLQueryWithFields:(NSArray *)fields sObject:(NSString *)sObject where:(NSString *)where groupBy:(NSArray *)groupBy having:(NSString *)having orderBy:(NSArray *)orderBy limit:(NSInteger)limit; 40 ネイティブ iOS の開発 SFRestAPI (Files) カテゴリ SOQL メソッドのパラメータは、SOQL クエリの構文に対応します。fields と sObject を除くすべてのパラ メータは、nil に設定することができます。 パラメータ名 説明 fields クエリする項目名の配列。 sObject クエリするオブジェクトの名前。 where 1 つ以上のクエリ条件を指定する式。 groupBy 結果レコードのグループ化に使用する項目名の配列。 having グループ化した結果を絞り込むための式 (通常、集計関 数を使用)。groupBy でのみ使用されます。 orderBy 結果レコードの並び替えに使用する項目名の配列。 limit 返されるレコードの最大数。 「SOQL SELECT の構文」 を参照してください。 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]; 41 ネイティブ iOS の開発 SFRestAPI (Files) カテゴリ メモ: この例では、最初のパラメータ (userId) に nil を渡します。この値で、コンテキスト (ログインし ている) ユーザの ID を使用するように requestForOwnedFilesList:page: メソッドに指示します。 pageNum パラメータに 0 を渡すと、最初のページを取得するようメソッドに指示します。 Files 機能およびネットワーキング機能についての詳細は、「ファイルとネットワーキング」を参照してくださ い。 メソッド SFRestAPI (Files) カテゴリでは、以下の操作がサポートされています。このカテゴリの詳細は、「SFRestAPI (Files) カテゴリ — 要求メソッド (iOS)」を参照してください。REST リクエストボディおよびレスポンスボディ についての詳細は、Files リソース を参照してください。 メソッド 説明 - (SFRestRequest *) requestForOwnedFilesList:(NSString *) userId page:(NSUInteger)page 指定されたユーザが所有するファイルのリストからペー ジを取得する要求を構築します。 - (SFRestRequest *) requestForFilesInUsersGroups:(NSString *)userId page:(NSUInteger)page ユーザのグループが所有するファイルのリストからペー ジを取得する要求を構築します。 - (SFRestRequest *) requestForFilesSharedWithUser:(NSString *)userId page:(NSUInteger)page ユーザと共有しているファイルのリストからページを 取得する要求を構築します。 - (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 *) requestForFileShares:(NSString *)sfdcId page:(NSUInteger)page このファイルを共有するエンティティのリストからペー ジを取得する要求を作成します。 - (SFRestRequest *) requestForAddFileShare:(NSString *)fileId 指定されたファイル ID のファイル共有を指定されたエ ンティティ ID に追加する要求を構築します。 42 ネイティブ iOS の開発 チュートリアル: ネイティブ iOS Warehouse アプリケー ションの作成 メソッド 説明 entityId:(NSString *)entityId shareType:(NSString*)shareType - (SFRestRequest *) requestForDeleteFileShare:(NSString *)shareId; 指定されたファイル共有を削除する要求を構築します。 - (SFRestRequest *) requestForUploadFile:(NSData *)data name:(NSString *)name description:(NSString *)description mimeType:(NSString *)mimeType 新しいファイルをサーバにアップロードする要求を構 築します。バージョンが 1 に設定された新しいファイ ルを作成します。 チュートリアル: ネイティブ iOS Warehouse アプリケーション の作成 前提条件 • このチュートリアルでは、基本的な在庫データベースを含む Warehouse アプリケーションを使用します。こ のアプリケーションを DE 組織にインストールする必要があります。既存の DE 組織にインストールする場 合、作成した既存の Warehouse コンポーネントをすべて削除してからインストールしてください。 1. インストール用 URL リンク https://login.salesforce.com/packaging/installPackage.apexp?p0=04ti0000000MMMT をクリックします。 2. すでにログインしている場合は、DE 組織のユーザ名とパスワードを入力します。 3. [Package Installation Details (パッケージインストールの詳細)] ページで、[Continue (次へ)] をクリックしま す。 4. [Next (次へ)] をクリックし、[Security Level (セキュリティレベル)] ページで [Next (次へ)] をクリックしま す。 5. [Install (インストール)] をクリックします。 6. [Deploy Now (今すぐデプロイ)] をクリックしてから、[Deploy (デプロイ)] をクリックします。 7. インストールが完了したら、右上のアプリケーションピッカーから [Warehouse (倉庫)] アプリケーション を選択できます。 8. データを作成するには、[データ] タブをクリックします。 9. [データを作成] ボタンをクリックします。 • 最新バージョンの Xcode と iOS SDK をインストールします。 43 ネイティブ iOS の開発 • ネイティブ iOS アプリケーションを作成する 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 forceios -g」と入力します。 このコマンドは、forceios パッケージを使用して Mobile SDK をグローバルにインストールします。-g オ プションでは、npm install を任意のディレクトリから実行できます。npm ユーティリティによりパッ ケージが /usr/local/lib/node_modules にインストールされ、/usr/local/bin のバイナリモジュー ルにリンクされます。大部分のユーザは /usr/local の「参照・更新」権限がないため、sudo オプショ ンが必要になります。 ネイティブ iOS アプリケーションを作成する このチュートリアルでは、Salesforce Mobile SDK の使用を開始する方法 (SDK のインストール方法や DE 組織を 使用したネイティブプロジェクトテンプレートのツアーを含む) を学習します。後続のチュートリアルでは、テ ンプレートアプリケーションを変更して、Warehouse スキーマと連携させる方法について説明します。 ステップ 1: 接続アプリケーションを作成する このステップでは、Force.com で接続アプリケーションを設定する方法を学習します。これを行うことで構築す るモバイルアプリケーションが認証され、ユーザの代わりに業界標準の OAuth 2.0 プロトコルを介して Force.com と安全に通信し、Force.com API にアクセスできるようになります。 1. DE 組織で あなたの名前 > [設定] をクリックし、[アプリケーションの設定] で [作成] > [アプリケーション] を クリックします。 2. [接続アプリケーション] で、[新規] をクリックして、[新規接続アプリケーション] ページを表示します。 3. [基本情報] で、フォームに次のように入力します。 • 接続アプリケーション名: My Native iOS App (私のネイティブ iOS アプリケーション) • API 参照名: 推奨値を受け入れます。 • 取引先責任者 メール: メールアドレスを入力します。 4. OAuth 設定で、[OAuth 設定の有効化] チェックボックスをオンにします。 5. [コールバック URL] を mysampleapp://auth/success に設定します。 6. [利用可能な OAuth 範囲] で、[データへのアクセスと管理] (api) および [ユーザに代わっていつでも要求を実 行] (refresh_token) をオンにして、[追加] をクリックします。 7. [保存] をクリックします。 44 ネイティブ iOS の開発 ステップ 2: ネイティブ iOS プロジェクトを作成する 設定を保存すると、作成した接続アプリケーションの詳細が表示されます。 • コールバック URL およびコンシューマ鍵を記録します。これらは、次のステップでネイティブアプリケー ションを設定するときに使用します。 • モバイルアプリケーションではコンシューマの秘密は使用しないため、この値は無視できます。 ステップ 2: ネイティブ iOS プロジェクトを作成する 新しい Mobile SDK プロジェクトを作成するには、ターミナルウィンドウで forceios ユーティリティを再度使用 します。 1. プロジェクトを作成するディレクトリに変更します。 2. iOS プロジェクトを作成するには、「forceios create」と入力します。 設定値ごとに、forceios ユーティリティによってプロンプトが表示されます。 3. アプリケーション種別に、「native」と入力します。 4. アプリケーション名に、「MyNativeiOSApp」と入力します。 5. 会社の識別子に、「com.acme.goodapps」と入力します。 6. 組織名に、「GoodApps, Inc.」と入力します。 7. 出力ディレクトリに、「tutorial/iOSNative」と入力します。 8. 接続アプリケーション ID に、接続アプリケーション定義からコンシューマ鍵をコピーして貼り付けます。 9. 接続アプリケーションのコールバック URI に、接続アプリケーション定義からコールバック URL をコピー して貼り付けます。 入力画面は次のように表示されます。 45 ネイティブ iOS の開発 ステップ 3: 新しい iOS アプリケーションを実行する ステップ 3: 新しい iOS アプリケーションを実行する 1. Xcode で [File (ファイル)] > [Open (開く)] を選択します。 2. 指定した出力フォルダに移動します。 3. アプリケーションの xcodeproj ファイルを開きます。 4. 左上隅にある [Run (実行)] ボタンをクリックすると、新しいアプリケーションが iOS シミュレータに表示さ れます。Xcode メニューで [Product (製品)] > [Destination (対象)] > [iPhone 6.0 Simulator (iPhone 6.0 シミュレー タ)] が選択されていることを確認してください。 5. アプリケーションを起動すると、初期スプラッシュ画面が表示された後で Salesforce ログイン画面が表示され ます。DE のユーザ名とパスワードを使用してログインします。 6. プロンプトが表示されたら、アプリケーションの左にある [Allow (許可)] をクリックして、Salesforce のデータ にアクセスします。DE 組織で定義されているユーザ名のリストを示す表が表示されます。 46 ネイティブ iOS の開発 ステップ 4: 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] initWithNibName:nil bundle:nil]; UINavigationController *navVC = [[UINavigationController alloc] 47 ネイティブ iOS の開発 ステップ 4: iOS アプリケーションの仕組みを探索する 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] autorelease]; } //if you want to add an image to your cell, here's how UIImage *image = [UIImage imageNamed:@"icon.png"]; cell.imageView.image = image; // Configure the cell to show the data. NSDictionary *obj = [self.dataRows objectAtIndex:indexPath.row]; cell.textLabel.text = [obj objectForKey:@"Name"]; //this adds the arrow to the right hand side. cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; return cell; } SFRestAPI 共有オブジェクトと SFRestRequest クラス RootViewController.viewDidLoad メソッドを確認すると、REST 要求がアプリケーションでどのように作成 および送信されるかがわかります。アプリケーションでは SOQL クエリのリテラル文字列が定義され、 SFRestAPI:requestForQuery: インスタンスメソッドに渡されます。このメソッドをコールするために、アプ リケーションは共有シングルトン SFRestAPI インスタンスにメッセージを送信します。メソッドは、SOQL ク エリをラップする書式設定済みの適切な SFRestRequest オブジェクトを作成し、それを返します。次に、 send:delegate: メッセージを共有 SFRestAPI オブジェクトに送信することで、アプリケーションはこのオブ ジェクトをサーバに転送します。 //Here we use a query that should work on either Force.com or Database.com SFRestRequest *request = [[SFRestAPI sharedInstance] requestForQuery:@"SELECT Name FROM 48 ネイティブ iOS の開発 リスト画面をカスタマイズする 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: コールバックが受信されると、返されたレコードがデータ行にコピーされ、 Warehouse ビューに表示されたデータが再度読み込まれます。次に、RootViewController クラスで SFRestDelegate インターフェースを実装するコードを示します。 #pragma mark - SFRestAPIDelegate - (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 } - (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 } コメントで示されるように、このコピーは、request:didLoadResponse: で代理メソッドが成功した場合にの み完全に実装されます。成功以外の応答の場合は、このテンプレートアプリケーションはメッセージをログ記録 するのみです。 リスト画面をカスタマイズする このチュートリアルでは、Warehouse スキーマ固有のアプリケーションとなるようにルートビューコントローラ を変更します。また、Merchandise カスタムオブジェクトから必要なすべての情報を取得できるように、既存の SOQL クエリを適合させます。 49 ネイティブ iOS の開発 ステップ 1: ルートビューコントローラを変更する ステップ 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 (保存)] をクリックします。 6. リファクタリングする前に自動スナップショットを取得するかどうかを Xcode から尋ねられたら、[Enable (有 効化)] をクリックします。 スナップショットが完了すると Refactoring ウィンドウが非表示になり、リファクタリングされたプロジェクトに 戻ります。RootViewController.h および RootViewController.m というファイル名が、 WarehouseViewController.h および WarehouseViewController.m になりました。プロジェクトコード内の RootViewController のすべてのインスタンスも、WarehouseViewController に変更されました。 ステップ 2: アプリケーションのルートビューを作成する ネイティブ iOS テンプレートアプリケーションでは、標準 User オブジェクトから Name 項目を抽出する SOQL クエリが作成されます。ただし、このチュートリアルでは、カスタムオブジェクトのレコードを使用します。 [Name (名前)]、[Quantitiy (数量)]、[Price (価格)] 項目を表示する詳細画面は、後から作成します。また、レコー ド ID も必要です。 カスタム Merchandise__c オブジェクトを操作する SOQL クエリを更新し、詳細画面に必要な項目を取得してみ ましょう。 1. プロジェクトナビゲータで、WarehouseViewController.m を選択します。 2. viewDidLoad メソッドまでスクロールします。 3. ビューの表示名を「Warehouse App」に更新します。次の行を変更します。 self.title = @"Mobile SDK Sample App" 変更後 self.title = @"Warehouse App" 50 ネイティブ iOS の開発 ステップ 3: アプリケーションを試す 4. 次の行で SOQL クエリを変更します。 SFRestRequest *request = [[SFRestAPI sharedInstance] requestForQuery:@"SELECT Name FROM User LIMIT 10"]; 変更後 SELECT Name, Id, Quantity__c, Price__c FROM Merchandise__c LIMIT 10 ステップ 3: アプリケーションを試す アプリケーションを作成して実行します。プロンプトが表示されたら、DE 組織にログインします。初期ページ に、次のような画面が表示されます。 この時点で Merchandise レコードをクリックしても何も起きません。次のチュートリアルでこれを修正します。 詳細画面を作成する 前のチュートリアルで、起動後に最大 10 個の Merchandise レコードを一覧表示するようにテンプレートアプリ ケーションを変更しました。このチュートリアルでは、詳細ビューおよびコントローラを作成して作業を終了し ます。また、リストビューコントローラと詳細ビューコントローラ間の通信も確立します。 51 ネイティブ iOS の開発 ステップ 1: アプリケーションの詳細ビューコントロー ラを作成する ステップ 1: アプリケーションの詳細ビューコントローラを作成する Warehouse ビューでユーザが Merchandise レコードをタップすると、IBAction はレコード固有の情報を生成し、 この情報を表示する DetailViewController からビューを読み込みます。ただし、このビューはまだ存在しな いので作成しましょう。 1. [File (ファイル)] > [New (新規)] > [File... (ファイル...)] > [Cocoa Touch] > [Objective-C class (Objective-C クラ ス)] をクリックします。 2. UIViewController をサブクラス化する DetailViewController という名前の新しい Objective-C クラスを 作成します。[With XIB for user interface (ユーザインターフェースに XIB を使う)] がオンになっていることを 確認します。 3. [Next (次へ)] をクリックします。 4. [Groups (グループ)] ドロップダウンメニューの Mobile Warehouse アプリケーションのクラスグループに新し いクラスを配置します。 Xcode により、Classes フォルダに 3 つの新しいファイル (DetailViewController.h、 DetailViewController.m、DetailViewController.xib) が作成されます。 5. プロジェクトナビゲータで DetailViewController.m を選択し、次のメソッド宣言を削除します。 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } このアプリケーションでは、NIB ファイルまたはバンドルを指定しないため、この初期化メソッドは必要あ りません。 6. プロジェクトナビゲータで DetailViewController.xib を選択し、Interface Builder を開きます。 7. [Utilities (ユーティリティ)] ビュー から、3 つの表示ラベル、2 つのテキスト項目、および 1 つ のボタンをビューレイアウトにドラッグします。次のような画面になるようにコントロールを並び替えてサ イズを変更します。 52 ネイティブ iOS の開発 ステップ 1: アプリケーションの詳細ビューコントロー ラを作成する 最上部の表示ラベルを今後名前表示ラベルと呼ぶことにします。この表示ラベルは動的です。次のチュート リアルでは、実行時にこれを適切な値にリセットするコントローラコードを追加します。 8. [Attributes (属性)] インスペクタで、価格および数量の静的な表示ラベルの表示テキストに下図の表示値を設 定します。Interface Builder で各表示ラベルを個別に選択し、[Text (テキスト)] ドロップダウンメニューの下に ある名前のない入力項目で表示テキストを指定します。 メモ: 必要に応じて表示ラベルの幅を調整し、表示テキストがすべて表示されるようにします。 9. [Attributes (属性)] インスペクタで、更新ボタンの表示テキストを下図の表示値に設定します。Interface Builder でボタンを選択し、[Title (タイトル)] ドロップダウンメニューの下にある名前のない入力項目でその表示テキ ストを指定します。 53 ネイティブ iOS の開発 ステップ 2: DetailViewController を設定する 10. 構築して実行し、エラーを確認します。まだ変更は表示されません。 詳細ビューの設計には、[Price (価格)] 項目、[Quantitiy (数量)] 項目、およびレコードの数量を更新するためのボ タンが表示されています。ただし、現時点では何も機能しません。次のステップでは、この設計を Warehouse レ コードに接続する方法を学習します。 ステップ 2: DetailViewController を設定する ビュー要素とそれらのビューコントローラ間の接続を確立するには、Xcode Interface Builder を使用して、UI 要素 とコード要素を接続します。 インスタンスプロパティを追加する 1. DetailViewController.h に、WarehouseViewController によって渡される値を格納するプロパティ (名 前、数量、価格、ID) を作成します。これらのプロパティを @interface ブロック内に配置します。次の名前 を使用して、それぞれの nonatomic および strong を宣言します。 @interface DetailViewController : UIViewController @property @property @property @property (nonatomic, (nonatomic, (nonatomic, (nonatomic, strong) strong) strong) strong) NSNumber NSNumber NSString NSString *quantityData; *priceData; *nameData; *idData; @end 2. DetailViewController.m の @implementation タグの直後に各プロパティを合成します。 @implementation DetailViewController @synthesize @synthesize @synthesize @synthesize nameData; quantityData; priceData; idData; IBOutlet 変数を追加する IBOutlet メンバー変数を使用すると、コントローラが各非静的コントロールを管理できます。手動でこれらを コーディングする代わりに、Interface Builder を使用して作成できます。Interface Builder には、便利な横並びの編 集ウィンドウがあるアシスタントエディタが用意されています。アシスタントエディタ用の領域を確保するに は、使用していないコントロールを非表示にして画面領域を再要求します。 1. プロジェクトナビゲータで、DetailViewController.xib ファイルをクリックします。 54 ネイティブ iOS の開発 ステップ 2: DetailViewController を設定する DetailViewController.xib ファイルが標準エディタで開きます。 2. [View (表示)] ツールバー の [Hide or Show Navigator (ナビゲータを表示/非表示)] をクリックし て、ナビゲータを非表示にします。または、Xcode メニューの [View (表示)] > [Navigators (ナビゲータ)] > [Hide Navigators (ナビゲータを非表示)] を選択することもできます。 3. [Editor (エディタ)] ツールバー の [Show the Assistant editor (アシスタントエディタを表示)] をク リックして、アシスタントエディタを開きます。または、Xcode メニューの [View (表示)] > [(Assistant Editor (アシスタントエディタ)] > [Show Assistant Editor (アシスタントエディタを表示)] を選択することもできます。 標準エディタで DetailViewController.xib を開いたため、アシスタントエディタには DetailViewController.h ファイルが表示されます。アシスタントエディタは、一緒に使用する可能性の最 も高いファイルを推測します。別のファイルを開く必要がある場合、アシスタントエディタの右上隅にある [Related Files (関連ファイル)] コントロールをクリックします。 4. DetailViewController.h のインターフェースブロックの上部に、空の中括弧のペアを追加します。 @interface DetailViewController : UiViewController <SFRestDelegate> { } 5. 標準エディタで、Ctrl キーを押しながら [Price (価格)] テキスト項目コントロールをクリックし、 DetailViewController.h ファイルの新しい中括弧ブロックにドラッグします。 6. ポップアップダイアログボックスで、新しいアウトレット _priceField に名前を付けて [Connect (接続)] を クリックします。 55 ネイティブ iOS の開発 ステップ 3: 指定のイニシャライザを作成する 7. [Quantity (数量)] テキスト項目についてステップ 2 と 3 を繰り返し、そのアウトレット _quantityField に名 前を付けます。 8. 名前表示ラベルについてステップ 2 と 3 を繰り返し、そのアウトレット _nameLabel に名前を付けます。 これで、インターフェースコードに次のブロックが含まれるようになりました。 @interface { __weak __weak __weak } DetailViewController : UIViewController IBOutlet UITextField *_priceField; IBOutlet UITextField *_quantityField; IBOutlet UILabel *_nameLabel; 更新ボタンイベントを追加する 1. Interface Builder で、[更新] ボタンを選択し、[Connections (接続)] インスペクタ を開きます。 2. [Connections (接続)] インスペクタで、[Touch Up Inside (タッチアップ (内))] の横にある円を選択し、 DetailViewController.h ファイルにドラッグします。閉じ中括弧の下にドロップしてください。 updateTouchUpInside という名前を付けて [接続] をクリックします。 Touch Up Inside イベントは、ユーザが更新ボタンに触れている指をボタン領域内で上げたことを通知します。 この通知を受信するたびにレコードの更新を実行します。 ステップ 3: 指定のイニシャライザを作成する では、コーディングに取り掛かりましょう。まず、名前、ID、数量、および価格を取得する DetailViewController に新しいイニシャライザメソッドを追加します。メソッド名は、命名規則に従って 「init」で開始する必要があります。 1. [Show the Standard Editor (標準エディタを表示)] をクリックして、ナビゲータを開きます。 2. この宣言を DetailViewController.h ファイルにある @end マーカーのすぐ上に追加します。 - (id) initWithName:(NSString *)recordName sobjectId:(NSString *)salesforceId quantity:(NSNumber *)recordQuantity price:(NSNumber *)recordPrice; 後で、このメソッドを使用してデータを DetailViewController に渡すように WarehouseViewController をコーディングします。 3. DetailViewController.m ファイルを開き、前のステップで作成した署名をファイルの最後にある @end マー カーのすぐ上にコピーします。 4. 実装ブロックのために、終了を示すセミコロンを中括弧のペアで置き換えます。 - (id) initWithName:(NSString *)recordName sobjectId:(NSString *)salesforceId quantity:(NSNumber *)recordQuantity price:(NSNumber *)recordPrice { } 56 ネイティブ iOS の開発 ステップ 3: 指定のイニシャライザを作成する 5. メソッド本文で、init メッセージをスーパークラスに送信します。戻り値を self に割り当てます。 self = [super init]; この 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 *)salesforceId quantity:(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. プロジェクトを構築して実行し、すべてのコーディングが完了していて、コンパイルエラーが発生していな いことを確認します。詳細ビューを起動するコードをまだ追加していないため、アプリケーションは最初の 状態と変わらないように見えます。 57 ネイティブ iOS の開発 ステップ 4: ビューコントローラ間の通信を確立する メモ: initWithName: メソッドで使用される [super init] メッセージは、内部的に [super initWithNibName:bundle:] をコールします。NIB 名またはバンドルを渡さないため、ここでは [super 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 オブジェク 58 ネイティブ iOS の開発 ステップ 4: ビューコントローラ間の通信を確立する トに保存されているデータを使用して、名前、Salesforce ID、数量、および価格の引数を設定します。完成し たコールは次のようになります。 DetailViewController *detailController = [[DetailViewController alloc] initWithName:[obj objectForKey:@"Name"] salesforceId:[obj objectForKey:@"Id"] 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 *)objectId quantity:(NSString *)quantity price:(NSString *)price; メソッドを実装するには、入力値を使用して SFRestRequest オブジェクトを作成し、要求オブジェクトを SFRestAPI の共有インスタンスに送信します。 2. DetailViewController.m ファイルの @implementation ブロックの上に次の行を追加します。 #import "SFRestAPI.h" 3. ファイルの最後にある @end マーカーのすぐ上に、updateWithObjectType:objectId:quantity:price: 署名をコピーし、その後に中括弧のペアを追加します。 - (void)updateWithObjectType:(NSString *)objectType objectId:(NSString *)objectId quantity:(NSString *)quantity price:(NSString *)price { } 59 ネイティブ iOS の開発 ステップ 4: ビューコントローラ間の通信を確立する 4. 実装ブロックで、[Quantitiy (数量)] 項目と [Price (価格)] 項目を格納する新しい NSDictionary オブジェクト を作成します。このオブジェクトを割り当てるには、目的の項目リストを含む dictionaryWithObjectsAndKeys: ... NSDictionary クラスメソッドを使用します。 - (void)updateWithObjectType:(NSString *)objectType objectId:(NSString *)objectId quantity:(NSString *)quantity price:(NSString *)price { NSDictionary *fields = [NSDictionary dictionaryWithObjectsAndKeys: quantity, @"Quantity__c", price, @"Price__c", nil]; } 5. SFRestRequest オブジェクトを作成します。このオブジェクトを割り当てるには、SFRestAPI 共有インスタ ンスで requestForUpdateWithObjectType:objectId:fields: インスタンスメソッドを使用します。 - (void)updateWithObjectType:(NSString *)objectType objectId:(NSString *)objectId quantity:(NSString *)quantity price:(NSString *)price { NSDictionary *fields = [NSDictionary dictionaryWithObjectsAndKeys: quantity, @"Quantity__c", price, @"Price__c", nil]; SFRestRequest *request = [[SFRestAPI sharedInstance] requestForUpdateWithObjectType:objectType objectId:objectId fields:fields]; } 6. 最後に、SFRestAPI 共有インスタンスで send:delegate: をコールして、新しい SFRestRequest オブジェ クトをサービスに送信します。この場合、DetailViewController が SFRestDelegate であるため、delegate 引数には self を指定してください。 - (void)updateWithObjectType:(NSString *)objectType objectId:(NSString *)objectId quantity:(NSString *)quantity price:(NSString *)price { NSDictionary *fields = [NSDictionary dictionaryWithObjectsAndKeys: quantity, @"Quantity__c", price, @"Price__c", nil]; SFRestRequest *request = [[SFRestAPI sharedInstance] requestForUpdateWithObjectType:objectType objectId:objectId fields:fields]; [[SFRestAPI sharedInstance] send:request delegate:self]; } 60 ネイティブ iOS の開発 ステップ 4: ビューコントローラ間の通信を確立する 7. ユーザが [更新] ボタンをタップしたときに updateWithObjectType:objectId:quantity:price: メソッド をコールするように updateTouchUpInside: アクションメソッドを編集します。 - (IBAction)updateTouchUpInside:(id)sender { // For Update button [self updateWithObjectType:@"Merchandise__c" objectId:self.idData quantity:[_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 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 } - (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 } 61 ネイティブ iOS の開発 ステップ 4: ビューコントローラ間の通信を確立する SFRestAPI インターフェースを実装するのに必要なのは、これらのメソッドだけです。このチュートリアル では、エラー、キャンセル、およびタイムアウト条件の単純な処理を保持できます。ただし、 request:didLoadResponse: メソッドは詳細ビューの目的に合わせて変更する必要があります。 UINavigationController スタックを使用して、更新実行後にリストビューに戻りましょう。 5. DetailViewController.m ファイルで、request:didLoadResponse: 代理メソッドの既存のコードを削除 します。その場所に、成功メッセージを記録してすぐにルートビューコントローラに戻るコードを追加しま す。修正したメソッドは次のようになります。 - (void)request:(SFRestRequest *)request didLoadResponse:(id)jsonResponse { NSLog(@"1 record updated"); [self.navigationController popViewControllerAnimated:YES]; } 6. アプリケーションを構築して実行します。Warehouse ビューで、いずれかの項目をクリックします。これで、 詳細ビューにアクセスしてその数量を編集できますが、キーボードを非表示にしたいときに非表示にならな いという問題があります。アプリケーションが完全に機能するには、もう少し工夫が必要です。 キーボードを非表示にする 画面のテキスト入力コントロールがタッチイベントに応答している限り、iOS キーボードは表示されたままにな ります。これには、Interface Builder の「First Responder (ファーストレスポンダ)」設定が関与しています。この 簡単なアプリケーションではデフォルトの UIKit の動作のみを使用しているため、ファーストレスポンダを設定 していません。その結果、iOS はビューの入力コントロールをファーストレスポンダとしてみなす可能性があり ます。どのコントロールも、キーボードを非表示にするように iOS に明示的に指示していない場合、キーボード は有効化されたままになります。 この問題は、タッチ対応編集コントロールにファーストレスポンダを放棄させることで解決できます。 1. DetailViewController.h の中括弧ブロックの下に、引数を取らず void を返す hideKeyboard という名前 の新しいインスタンスメソッドを追加します。 - (void)hideKeyboard; 2. 実装ファイルで、このメソッドを実装して resignFirstResponder メッセージをビューの各タッチ対応編集 コントロールに送信します。 - (void)hideKeyboard { [_quantityField resignFirstResponder]; [_priceField resignFirstResponder]; } 残りの問題は、hideKeyboard メソッドをどこでコールするかだけです。ユーザがテキスト入力コントロー ルの外側をタップしたらキーボードが非表示になるようにします。色々なイベントを試すことができると思 いますが、どのような環境でもバックグラウンドのタッチを確実にキャッチできるのは [UIResponder touchesEnded:withEvent:] だけです。 3. このイベントは、DetailViewController が継承するクラスですでに宣言されているため、 DetailViewController.h ファイルで再度宣言する必要はありません。代わりに、DetailViewController.m ファイルで、メソッド本文の外側の新しい行に次の不完全なコードを入力します。 - (void)t 62 ネイティブ iOS の開発 ステップ 4: ビューコントローラ間の通信を確立する DetailViewController クラス階層の一致するインスタンスメソッドのリストがポップアップメニューで表 示されます。 メモ: ポップアップメニューが表示されない場合、次に説明するコードを入力します。 4. ポップアップメニューで、touchesEnded:withEvent: メソッドを強調表示して Enter キーを押します。エ ディタによって、完全なメソッド署名がファイルに入力されます。開き括弧を入力して Enter キーを押すだ けで、エディタによってスタブメソッドが完成します。このスタブ内で、hideKeyboard メッセージを self に送信します。 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ [self hideKeyboard]; } 通常、イベントハンドラでは、独自のコードを追加する前にスーパークラスバージョンをコールすることが 想定されています。ただし、「iOS Developer Library」に説明されているように、この場合、スーパーコール を除外するのが一般的な使用パターンです。唯一「わかっていること」は、次のコードを含む他のタッチイ ベントハンドラを実装する必要もあるということです。 – touchesBegan:withEvent: – touchesMoved:withEvent: – touchesCancelled:withEvent: これは空のスタブ実装を追加するだけで済みます。 5. Xcode エディタを使用して、touchesEnded: スタブを追加したときと同じ方法でこれらのスタブを追加しま す。最終的なコードが次のようになっていることを確認します。 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ [self hideKeyboard]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{ } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ } viewWillAppear を使用したクエリの更新 viewDidLoad メソッドでは、最初に読み込まれたときのビューを設定できます。WarehouseViewController 実装では、リストビューと詳細ビューの両方を入力する REST API クエリがこのメソッドにあります。ただし、 WarehouseViewController はルートビューを表しているため、viewDidLoad 通知はビューの初期化時に 1 回 しかコールされません。これはどういう意味でしょうか? ユーザが詳細ビューで数量を更新してリストビューに 戻っても、クエリは更新されません。そのため、詳細ビューの同じレコードに戻っても、ユーザが期待する更新 された値は表示されません。 63 ネイティブ iOS の開発 ステップ 5: アプリケーションを試す クエリを処理するには、別のメソッドが必要です。viewWillAppear メソッドは、そのビューが表示されるたび にコールされます。このメソッドを WarehouseViewController に追加して、SOQL クエリをそこに移動しま しょう。 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]; //Here we use a query that should work on either Force.com or Database.com 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 サンプル アプリケーションには、独自のアプリケーションで確認および操作できる多くの機能が含まれています。 64 ネイティブ iOS の開発 iOS ネイティブサンプルアプリケーション • RestAPIExplorer では、ネイティブのすべての REST API ラッパーが実行されます。これは、 native/SampleApps/RestAPIExplorer の Mobile SDK for iOS にあります。 • NativeSqlAggregator には、SQL の集約例と、ネイティブ SmartStore の実装が表示されます。このサンプルア プリケーションは、native/SampleApps/NativeSqlAggregator の SDK for iOS にあります。 • FileExplorer には、Files API と、その基盤となる MKNetwork ネットワーク機能強化が示されます このサンプ ルアプリケーションは、native/SampleApps/FileExplorer の SDK for iOS にあります。 65 第6章 ネイティブ Android の開発 トピック: • • • • • • • Android ネイティブクイックスター ト ネイティブ Android の要件 Android プロジェクトの作成 Eclipse でのサンプルプロジェクト の設定 ネイティブ Android アプリケー ションの開発 チュートリアル: ネイティブ Android Warehouse アプリケーショ ンの作成 Android ネイティブサンプルアプ リケーション Salesforce Mobile SDK には、Android でネイティブモバイルアプリケー ションを開発するためのライブラリおよびサンプルプロジェクトが用 意されています。 Android のネイティブ SDK では、次の 2 つの主要な機能が提供されま す。 • OAuth2 ログインプロセスの自動化。これにより、プロセスをアプ リケーションに統合しやすくなります。 • Salesforce REST API へのアクセス。アクセスを簡略化するユーティ リティクラスが使用されます。 Android Salesforce Mobile SDK には、ネイティブアプリケーションのサ ンプルがいくつか含まれています。また、新しいアプリケーションを すばやく作成する ant ターゲットも提供されます。 66 ネイティブ Android の開発 Android ネイティブクイックスタート Android ネイティブクイックスタート すばやく開始する手順は、次のとおりです。 1. ネイティブ Android 要件をすべて満たしていることを確認します。 2. Mobile SDK for Android をインストールします。 3. コマンドラインで、新しい Android プロジェクトを作成する forcedroid アプリケーションを実行し、Eclipse ま たはコマンドラインからそのアプリケーションを実行します。 4. Eclipse でサンプルプロジェクトを設定します。 ネイティブ Android の要件 Mobile SDK 2.2 Android の開発には、次のソフトウェアが必要です。 • Java JDK 6 以降 — http://www.oracle.com/downloads。 • Apache Ant 1.8 以降 — http://ant.apache.org。 • Android SDK Tools バージョン 21 以降 —http://developer.android.com/sdk/installing.html。 メモ: 最良の結果を得るには、対象バージョンだけでなく、Android SDK の以前のすべてのバージョ ンもインストールします。 • Eclipse — https://www.eclipse.org。サポートされている Eclipse の最小バージョンについては、Android 開発ツールに関する Web サイトを参照してください。 • Eclipse バージョン 21 以降用の Android ADT (Android 開発ツール) プラグイン — http://developer.android.com/sdk。 • アプリケーションをエミュレータで実行するには、Platform 2.2 以降 (4.0 以降を推奨) を対象とする Android 仮想デバイス (AVD) を少なくとも 1 つ設定する必要があります。Eclipse での AVD の設定方法については、 http://developer.android.com/guide/developing/devices/managing-avds.html の手順を参照して ください。 Salesforce 側には、以下も必要です。 • Salesforce Mobile SDK 2.2 for Android。「iOS のインストール」を参照してください。 • 接続アプリケーションが存在する Salesforce Developer Edition 組織。 SalesforceSDK プロジェクトは、Android 3.0 (Honeycomb) ライブラリを使用して作成されます。この主な理由 は、ファイルシステムの暗号化機能に対してランタイム時に条件付きチェックを実行できるようにするためで す。このチェックは、以前の Android プラットフォームでは省略されます。このため、最小サポートの Android 2.2 を含む以前のバージョンの Android アプリケーションでは、引き続き salesforcesdk.jar を使用できます。 Android プロジェクトの作成 新しいアプリケーションを作成するには、コマンドラインで forcedroid をもう一度使用します。アプリケーショ ンを設定する方法は 2 つあります。 • forcedroid アプリケーションのプロンプトで対話形式でアプリケーションオプションを設定する。 67 ネイティブ Android の開発 • Android プロジェクトの作成 直接コマンドラインでアプリケーションオプションを指定する。 対話形式でのアプリケーションオプションの指定 対話形式でアプリケーションオプションを入力するには、次のいずれかを実行します。 • Mobile SDK をグローバルにインストールした場合は、「forcedroid create」と入力する。 • Mobile SDK をローカルにインストールした場合は、「<forcedroid_path>/node_modules/.bin/forcedroid create」と入力する。 forcedroid ユーティリティにより、各設定オプションが表示されます。 アプリケーションオプションの直接指定 また、完全な forcedroid コマンド文字列を入力して、設定を直接指定することもできます。使用方法に関する情 報を表示するには、引数を指定せずに「forcedroid」と入力します。次のように使用可能なオプションのリス トが表示されます。 $ node_modules/.bin/forcedroid Usage: forcedroid create --apptype=<Application Type> (native, hybrid_remote, hybrid_local) --appname=<Application Name> --targetdir=<Target App 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> ('true' or 'false', false by default)] この情報を使用して、「forcedroid create」と入力してからオプションおよび値を入力します。次に例を示 します。 $ node_modules/.bin/forcedroid create --apptype="native" --appname="packagetest" --targetdir="PackageTest" --packagename="com.test.my_new_app" Eclipse でのアプリケーションのインポートおよび作成 Eclipse エディタで新しいアプリケーションを作成して実行する手順は、次のとおりです。 1. Eclipse を起動し、ワークスペースディレクトリとしてターゲットディレクトリを選択します。 2. [Eclipse] > [Preferences (個人設定)] を選択し、[Android] セクションを選択して、Android SDK の場所を入力 します。 3. [OK] をクリックします。 68 ネイティブ Android の開発 Android プロジェクトの作成 4. [File (ファイル)] > [Import (インポート)] を選択し、[General (一般)] > [Existing Projects into Workspace (既存の プロジェクトをワークスペースへ)] を選択します。 5. [Next (次へ)] をクリックします。 6. ルートディレクトリとして forcedroid/native ディレクトリを指定します。表示されるリストの横にある [すべて選択解除] をクリックし、リストを参照して SalesforceSDK プロジェクトにチェックを入れます。 7. –use_smartstore=true を設定する場合、SmartStore プロジェクトにもチェックを入れます。 8. [Import (インポート)] をクリックします。 9. ステップ 4 ~ 8 を繰り返します。ステップ 6 で、ターゲットディレクトリをルートとして選択し、新しいプ ロジェクトのみを選択します。 プロジェクトのインポートが完了したら、Eclipse によって自動的にワークスペースが作成されます。このプロセ スには数分かかる場合があります。ステータスバーにエラーが表示されていなければ、プロジェクトを実行でき ます。 1. Eclipse ワークスペースで、Ctrl キーを押しながらプロジェクトをクリックするか、プロジェクトを右クリッ クします。 2. ポップアップメニューから、[Run As (別のユーザとして実行)] > [Android Application (Android アプリケーショ ン)] を選択します。 Eclipse によってエミュレータまたは接続されている Android デバイスでアプリケーションが起動します。 コマンドラインからのアプリケーションの作成および実行 コマンドラインからコマンドプロンプトに戻ると、プロジェクトを設定およびクリーンアップするための Android ユーティリティの実行手順が forcedroid スクリプトにより出力されます。コマンドラインからアプリケーション を作成および実行する場合にのみこれらの手順を実行します。 1. 新しいアプリケーションを作成する前に、コマンドプロンプトで次のコマンドを実行して SalesforceSDK プロ ジェクトを構築します。 cd $SALESFORCE_SDK_DIR/native/SalesforceSDK $ANDROID_SDK_DIR/tools/android update project -p . -t <id> ant clean debug ここで、SALESFORCE_SDK_DIR は SDK インストールディレクトリを、ANDROID_SDK_DIR は Android SDK ディレクトリを指し示しています。 メモ: -t <id> パラメータは、対象の Android バージョンの API レベルを指定します。システムにイ ンストールされている API バージョンの ID を確認するには、android.bat list targets を使用 します。サポートされている API レベルは、「ネイティブ Android の要件」を参照してください。 2. コマンドプロンプトで次のコマンドを実行して SmartStore プロジェクトを構築します。 cd $SALESFORCE_SDK_DIR/hybrid/SmartStore $ANDROID_SDK_DIR/tools/android update project -p . -t <id> ant clean debug ここで、SALESFORCE_SDK_DIR は SDK インストールディレクトリを、ANDROID_SDK_DIR は Android SDK ディレクトリを指し示しています。 69 ネイティブ Android の開発 Android プロジェクトの作成 3. 新しいアプリケーションを構築するには、コマンドプロンプトで次のコマンドを実行します。 cd <your_project_directory> $ANDROID_SDK_DIR/tools/android update project -p . -t <id> ant clean debug ここで、ANDROID_SDK_DIR は Android SDK ディレクトリを指し示します。 4. エミュレータが実行されていない場合は、Android AVD マネージャを使用して起動します。デバイスを使用 している場合は、接続します。 5. コマンドプロンプトで次のコマンドを入力します。 ant installd メモ: 次の警告を無視しても問題はありません。 It seems that there are sub-projects. If you want to update them please use the --subprojects parameter. 作成した Android プロジェクトには、作成および実行が可能な簡単なアプリケーションが含まれます。 forcedroid コマンドパラメータ 次の表に、forcedroid コマンドパラメータを示します。 パラメータ名 説明 --apptype 次のいずれかになります。 • • • 「native」 「hybrid_remote」(VisualForce を使用するサーバ側ハ イブリッドアプリケーション) 「hybrid_local」(VisualForce を使用しないクライアン ト側ハイブリッドアプリケーション) --appname アプリケーションの名前 --targetdir プロジェクトを作成するフォルダ。フォルダが存在し ていない場合は、スクリプトで作成されます。 --packagename アプリケーションのパッケージ識別子 (「com.acme.app」 など)。 --apexpage (ハイブリッドリモートアプリケーションのみ) Apex の 開始ページへのサーバパス。 たとえ ば、/apex/MyAppStartPage のように入力します。 --usesmartstore=true (省略可能) オフラインデータに SmartStore を使用する 場合にのみ含めます。指定されていない場合、デフォ ルトの false に設定されます。 70 ネイティブ Android の開発 Eclipse でのサンプルプロジェクトの設定 Eclipse でのサンプルプロジェクトの設定 コピーしたリポジトリには、実行可能な他のサンプルアプリケーションがあります。これらを Eclipse にインポー トする手順は、次のとおりです。 1. Eclipse を起動し、ワークスペースディレクトリとして —target_dir を選択します。 2. [Window (ウィンドウ)] > [Preferences (個人設定)] を選択し、[Android] セクションを選択して、Android SDK の場所を入力します (まだ実行していない場合)。[OK] をクリックします。 3. [File (ファイル)] > [Import (インポート)] を選択し、[General (一般)] > [Existing Projects into Workspace (既存の プロジェクトをワークスペースへ)] を選択します。 4. [Next (次へ)] をクリックします。 5. ルートディレクトリとして forcedroid/native を選択し、Android プロジェクトファイルに示すプロジェク トをインポートします。 Android プロジェクトファイル $NATIVE_DIR 内には、いくつかのプロジェクトがあります。 • SalesforceSDK — Salesforce Mobile SDK プロジェクト。OAuth2 および REST API コールのサポートを提供 します。 • test/SalesforceSDKTest — SalesforceSDK プロジェクトをテストするアプリケーション • TemplateApp — Mobile SDK を使用する新しいネイティブアプリケーションを作成するときにテンプレート として使用されるアプリケーション • test/TemplateAppTest — TemplateApp プロジェクトをテストするアプリケーション • SampleApps/RestExplorer — REST API コールを探索するための、SalesforceSDK を使用するサンプルアプ リケーション • SampleApps/FileExplorer — Files API を示すサンプルアプリケーション • SampleApps/NativeSqlAggregator — SmartStore を使用するサンプルネイティブアプリケーション ネイティブ Android アプリケーションの開発 Salesforce Mobile SDK のネイティブ Android バージョンでは、ホストデバイスの Android オペレーティングシス テムを直接使用するリッチモバイルアプリケーションを作成できます。このようなアプリケーションを作成する には、Java および Android 開発を十分に理解し、Mobile SDK ネイティブクラスを使用するコードを記述できる 必要があります。 create_native スクリプト GitHub から Mobile SDK を手動でインストールした場合、forcedroid ではなく create_native スクリプトを使 用して、新しいネイティブプロジェクトを作成します。create_native スクリプトは、指定のアプリケーショ ンフォルダを作成し、プロジェクトファイル、ビルドファイル、マニフェストファイル、リソースファイルをそ のフォルダに格納します。次に、TemplateApp プロジェクト全体を新しいフォルダにコピーします。その後、新 しいアプリケーションの設定に合わせて、プロジェクトのプロパティ、ファイル名、クラス名、ディレクトリパ 71 ネイティブ Android の開発 Android アプリケーションの構造 スを更新します。これにより、TemplateApp プロジェクトで使用されるすべての設定およびコンポーネントが新 しいプロジェクトで複製されます。 新しいアプリケーションで SmartStore がサポートされている場合、スクリプトで次の作業も実行されます。 • SmartStore サポートライブラリをアプリケーションディレクトリに追加する。 • 新しいプロジェクトのプロパティで SmartStore ライブラリを参照する。 • SalesforceSDKManager ではなく SalesforceSDKManagerWithSmartStore を拡張するようにアプリケー ションクラスを変更する。 最後に、スクリプトによって次の重要なメッセージが表示されます。 “Before you ship, make sure to plug in your oauth client id and callback url in: ${target.dir}/res/values/bootconfig.xml” OAuth クライアント ID およびコールバック URL の取得場所がわからない場合、Salesforce 組織の接続アプリケー ション定義を調べます。OAuth クライアント ID は、接続アプリケーションのコンシューマ鍵です。コールバッ ク URL は、接続アプリケーションの作成時に指定した URL です。明示的な名前の <string> ノードがいくつか 含まれているプロジェクトの res/values/bootconfig.xml ファイルでこれらのキーを入力します。次に、 bootconfig.xml ファイルの例を示します。 <?xml version="1.0" encoding="utf-8"?> <resources> <string name="remoteAccessConsumerKey">3MVG92.uWdyphVj4bnolD7yuIpCQsNgddW tqRND3faxrv9uKnbj47H4RkwheHA2lKY4cBusvDVp0M6gdGE8hp</string> <string name="oauthRedirectURI">sfdc:///axm/detect/oauth/done</string> <string-array name="oauthScopes"> <item>api</item> </string-array> </resources> create_native スクリプトを使用すると、oauthRedirectURI および remoteAccessConsumerKey 文字列にダ ミーの値が自動入力されます。これらの値を接続アプリケーション定義の文字列で置き換えます。 Android アプリケーションの構造 通常、Mobile SDK を使用するネイティブ Android アプリケーションには、次のクラスとアクティビティが必要 になります。 • android.app.Application を拡張するアプリケーションエントリポイントクラス • android.app.Activity を拡張する 1 つ以上のアクティビティ Mobile SDK では、次の作業を実行します。 • android.app.Application を拡張するスタブクラスを作成する。 • onCreate() を Application スタブクラスに実装して SalesforceSDKManager.initNative() をコールす る。 • SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivity を拡張する。 この拡張は省略可能ですが、実行することをお勧めします。 最上位レベルの SalesforceSDKManager クラスは、パスコードを使用するアプリケーションにはパスコード機 能を実装し、パスコードを使用しないアプリケーションには空白を入力します。また、ログインのフェーズを設 72 ネイティブ Android の開発 Android アプリケーションの構造 定したり、ログアウト後にクリーンアップしたり、システムレベルアカウントが削除されたときにアプリケー ションに情報を通知する特殊なイベントウォッチャを提供したりします。OAuth プロトコルは、内部クラスで自 動的に処理されます。 SalesforceActivity、SalesforceListActivity、SalesforceExpandableListActivity クラスは、アプリ ケーションの一時停止および再開イベントや関連するパスコード管理を自由に処理できます。アプリケーション のメインアクティビティだけでなくすべてのアクティビティで、これらのいずれかのクラスを拡張することをお 勧めします。アクティビティで別の基本クラスを使用する場合、SalesforceActivity にある一時停止および再 開プロトコルを自分で置き換える必要があります。 アクティビティ内で、Salesforce REST API をコールして Salesforce オブジェクトを操作します。Mobile SDK に は、REST 要求および応答フローを簡略化する com.salesforce.androidsdk.rest パッケージが用意されてい ます。 ユーザインターフェースレイアウト、画像サイズ、文字列、および XML ファイルのその他のリソースを定義し てカスタマイズします。SDK は、内部的に R クラスインスタンスを使用して、リソースを取得および操作しま す。ただし、クライアントアプリケーションは Mobile SDK のリソースに直接アクセスできるため、これらの機 能を管理するためにコードを記述する必要はありません。 73 ネイティブ Android の開発 ネイティブ API パッケージ ネイティブ API パッケージ Salesforce Mobile SDK では、ネイティブ Android API が Java パッケージにグループ化されています。これらのパッ ケージの概要と要点については、「Android パッケージおよびクラス」 (ページ 283)を参照してください。 74 ネイティブ Android の開発 ネイティブクラスの概要 ネイティブクラスの概要 この Mobile SDK ネイティブクラスの概要では、各クラスの関連する詳細や必要なクラスがどこにあるのかにつ いて説明します。 SalesforceSDKManager クラス SalesforceSDKManager クラスは、Salesforce Mobile SDK を使用するすべてのネイティブ Android アプリケー ションのエントリポイントです。このクラスは次のメカニズムを提供します。 • ログインおよびログアウト • パスコード • ユーザデータの暗号化および復号化 • 文字列変換 • ユーザエージェントアクセス • アプリケーションの終了 • アプリケーションのクリーンアップ initNative() メソッド 起動時に、静的 initNative() メソッドをコールして、シングルトン SalesforceSDKManager オブジェクトを 初期化します。このメソッドには次の 4 つの引数があります。 パラメータ名 説明 applicationContext アプリケーションのコンテキストを説明する Context のインスタンス。Application 拡張クラスでは、コー ルを getApplicationContext() に渡してこのパラメー タを満たすことができます。 keyImplementation KeyInterface Mobile SDK インターフェースの実装の インスタンス。このインターフェースを実装する必要 があります。 mainActivity メインアクティビティを表示するクラスの記述子。メ インアクティビティは、ログイン後に最初に表示され るアクティビティです。 loginActivity (省略可能) カスタム LoginActivity クラスのクラス記 述子。 次に、TemplateApp の例を示します。 SalesforceSDKManager.initNative(getApplicationContext(), new KeyImpl(), MainActivity.class); この例では、KeyImpl は、KeyInterface のアプリケーションの実装です。MainActivity は、 SalesforceActivity をサブクラス化し、ここではログイン後に最初にコールされるアクティビティとして指定 されています。 75 ネイティブ Android の開発 KeyInterface インターフェース logout() メソッド SalesforceSDKManager.logout() メソッドは、ユーザデータをクリアします。たとえば、ユーザ固有の独自 リソースを取り入れたが、次のユーザセッションには保持したくないとします。SmartStore は、ログアウト時に ユーザデータおよびアカウント情報を自動的に破棄します。 クリーンアップ後 (推奨) に、メソッド上書きのどこかでスーパークラスメソッドを常にコールします。次に、擬 似コード例を示します。 @Override public void logout(Activity frontActivity) { // Clean up all persistent and non-persistent app artifacts // Call superclass after doing your own cleanup super.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() メソッドに渡す必須のインターフェースで す。 76 ネイティブ Android の開発 AccountWatcher クラス getKey() メソッド Base64 でエンコードされた暗号化キーを getKey() 抽象メソッドから返す必要があります。Encryptor.hash() および Encryptor.isBase64Encoded() ヘルパーメソッドを使用して、適切なキーを生成します。Mobile SDK は、キーを使用してアプリケーションデータおよびアカウント情報を暗号化します。 AccountWatcher クラス AccountWatcher は、ユーザのアカウントが設定で削除された場合にアプリケーションに通知します。 AccountWatcher を使用しない場合、アプリケーションはこれらの変更の通知を取得できません。カウントが削 除されたタイミングを把握して、アカウントのパスコードやデータを適切に破棄し、ログアウトを開始できるよ うにすることは重要です。 AccountWatcher は、各アプリケーションで実装する必要のある内部インターフェース AccountRemoved を定 義します。 SalesforceSDKManager は、このインターフェースを実装して、アプリケーションの現在の (フロ ント) アクティビティを終了し、パスコード (使用している場合) および暗号化キーをリセットします。 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() をコールします。 @Override public void onPause() { passcodeManager.onPause(this); super.onPause(); } 77 ネイティブ Android の開発 Encryptor クラス PasscodeManager.onResume() メソッドの boolean 型の戻り値を他のアクションを再開するための条件として 使用します。アプリケーションの onResume() の実装では、PasscodeManager バージョンをコールする前にスー パークラスメソッドをコールします。次に例を示します。 @Override public void onResume() { super.onResume(); // Bring up passcode screen if needed passcodeManager.onResume(this); } recordUserInteraction() このメソッドは、最近のユーザ操作の大部分のタイムスタンプを保存します。アクティビティの onUserInteraction() メソッドで PasscodeManager.recordUserInteraction() をコールします。次に例を 示します。 @Override public void onUserInteraction() { 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 を拡張していない場合、これらの各アク ティビティにパスコードプロトコルを少し追加する必要があります。「パスコードの使用」を参照してくださ い。 78 ネイティブ Android の開発 UI クラス これらの各アクティビティクラスには、次の 1 つの抽象メソッドが含まれています。 public abstract void onResume(RestClient client); このメソッドは、クラスによって実装される Activity.onResume() メソッドをオーバーロードします。クラス メソッドは、RestClient インスタンスをインスタンス化した後でオーバーロードをコールします。このメソッ ドを使用して、渡されるクライアントをキャッシュし、そのクライアントを使用して REST 要求を実行します。 UI クラス com.salesforce.androidsdk.ui パッケージのアクティビティは、すべての Mobile SDK アプリケーションに 共通する UI リソースを表しています。XML を介して、これらのリソースのスタイル、スキン、テーマを設定し たり、カスタマイズしたりできます。SalesforceActivity、SalesforceListActivity、 SalesforceExpandableListActivity を除き、実行時にリソースを置き換えることを目的として、これらのア クティビティクラスを上書きしないでください。 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 インスタンスを取得した場 合、このメソッドをコールします。 79 ネイティブ Android の開発 RestRequest クラス sendSync() メソッド 要求に対してどの程度の情報を提供できるかに応じて、RestClient.sendSync() の 3 つのオーバーロードから 選択できます。 sendAsync() メソッド RestClient.sendAsync() メソッドは、WrappedRestRequest の新しいインスタンスの RestRequest オブジェ クトをラップします。次に、WrappedRestRequest オブジェクトを要求キューに追加して、そのオブジェクトを 返します。待機中に要求をキャンセルする場合、WrappedRestRequest オブジェクトで cancel() をコールしま す。 getRequestQueue() メソッド 基盤となる RequestQueue オブジェクトにアクセスするには、RestClient インスタンスで restClient.getRequestQueue() をコールします。RequestQueue オブジェクトを使用すると、待機中の要求 を直接キャンセルまたは操作できます。たとえば、restClient.getRequestQueue().cancelAll() をコール して待機中の要求キュー全体をキャンセルできます。「要求キューの管理」のコード例を参照してください。 RestRequest クラス RestRequest クラスは、アプリケーションから提供されるデータに基づいて REST API 要求を作成および書式 設定します。これは、Mobile SDK によって実装され、自身のインスタンスのファクトリとして機能します。 RestRequest のインスタンスを直接作成しないでください。代わりに、適切な RestRequest の静的ファクトリ メソッド (RestRequest.getRequestForCreate() など) をコールします。要求を送信するには、返された RestRequest オブジェクトを RestClient.sendAsync() または RestClient.sendSync() に渡します。「REST API の使用」を参照してください。 RestRequest クラスは、Salesforce REST API および SOAP API によって提供される標準の Salesforce データ操作 をネイティブに処理します。サポートされる操作は次のとおりです。 操作 パラメータ 説明 Versions なし Salesforce バージョンのメタデータを 返します。 Resources API バージョン リソース名および URI を含む、指定 された API バージョンで使用可能な リソースを返します。 Metadata API バージョン、オブジェクト種別 オブジェクトの完全なメタデータコ レクションを返します。 DescribeGlobal API バージョン Describe API バージョン、オブジェクト種別 1 つのオブジェクト種別の説明を返 します。 組織で使用できるすべてのオブジェ クトとそのメタデータのリストを返 します。 80 ネイティブ Android の開発 FileRequests クラス 操作 パラメータ 説明 Create API バージョン、オブジェクト種 指定したオブジェクトに新しいレ 別、値オブジェクトに対する項目名 コードを作成します。 の対応付け Retrieve API バージョン、オブジェクト種 オブジェクト ID でレコードを取得 別、オブジェクト ID、項目のリスト します。 Update API バージョン、オブジェクト種 指定された対応付けでオブジェクト 別、オブジェクト ID、値オブジェク を更新します。 トに対する項目名の対応付け Upsert API バージョン、オブジェクト種 外部 ID が外部 ID 項目に現在存在し 別、外部 ID 項目、外部 ID、値オブ ているかどうかに基づいて、外部 ジェクトに対する項目名の対応付け データからオブジェクトを更新また は挿入します。 Delete API バージョン、オブジェクト種 別、オブジェクト ID 指定された ID を持つ特定のタイプ のオブジェクトを削除します。 適切な RestRequest インスタンスを取得するには、実行する操作に一致する RestRequest 静的メソッドをコー ルします。次に、RestRequest 静的メソッドを示します。 • • • • • • • • • • • • getRequestForCreate() getRequestForDelete() getRequestForDescribe() getRequestForDescribeGlobal() getRequestForMetadata() getRequestForQuery() getRequestForResources() getRequestForRetrieve() getRequestForSearch() getRequestForUpdate() getRequestForUpsert() getRequestForVersions() これらのメソッドは、RestClient のインスタンスに渡す RestRequest オブジェクトを返します。RestClient クラスは、要求を送信する同期メソッド (sendSync()) および非同期メソッド (sendAsync()) を提供します。UI スレッドから要求を送信する場合は、sendAsync() を使用します。 sendSync() は、非 UI スレッド (アクティ ビティによって実行されるサービスまたはワーカースレッドなど) の場合にのみ使用します。 FileRequests クラス FileRequests クラスは、ファイル操作要求を構築するメソッドを提供します。各メソッドは、新しい RestRequest オブジェクトを返します。アプリケーションは、このオブジェクトを Salesforce サービスに送信して要求を処理 します。たとえば、次のコードスニペットは ownedFilesList() メソッドをコールして RestRequest オブジェ 81 ネイティブ Android の開発 FileRequests クラス クトを取得します。次に、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 リ クエストボディおよびレスポンスボディについての詳細は、Files リソース を参照してください。 メソッド名 説明 ownedFilesList 指定されたユーザが所有するファイルのリストからペー ジを取得する要求を構築します。 filesInUsersGroups ユーザのグループが所有するファイルのリストからペー ジを取得する要求を構築します。 filesSharedWithUser ユーザと共有しているファイルのリストからページを取 得する要求を構築します。 fileDetails 特定のバージョンのファイルの詳細を取得する要求を構 築します。 batchFileDetails 1 つの要求で 1 つ以上のファイルの最新の詳細を取得する 要求を構築します。 fileRendition ファイル (およびバージョン) の特定のページのプレビュー/ 変換を取得する要求を構築します。 fileContents この特定のファイルの実際のバイナリコンテンツを取得 する要求を構築します。 fileShares このファイルの共有先のエンティティのリストからペー ジを取得する要求を構築します。 addFileShare 指定されたファイル ID のファイル共有を指定されたエン ティティ ID に追加する要求を構築します。 deleteFileShare 指定されたファイル共有を削除する要求を構築します。 uploadFile 新しいファイルをサーバにアップロードする要求を構築 します。新しいファイルを作成します。 82 ネイティブ Android の開発 WrappedRestRequest クラス WrappedRestRequest クラス WrappedRestRequest クラスは、Volley Request クラスをサブクラス化します。WrappedRestRequest オブジェ クトは作成しません。RestClient.sendAsync() メソッドは、このクラスを使用して、渡された RestRequest オブジェクトをラップし、コール元に返します。返されたこのオブジェクトで cancel() メソッドをコールし て、「待機中」の要求をキャンセルできます。 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 の実装では、単にバージョン文字列を保存して比較するだけです。 83 ネイティブ Android の開発 ユーティリティクラス ユーティリティクラス util パッケージの大部分のクラスは内部で使用されますが、いくつかのクラスはサードパーティ開発者にも利 点があります。 クラス 説明 EventsObservable Mobile SDK for Android が伝搬するすべてのイベントの リストは、ソースコードを参照してください。 EventsObserver イベントを傍受するにはこのインターフェースを実装 します。この機能は、特定のタイプのイベント発生時 に特殊な操作を実行する場合に便利です。 TokenRevocationReceiver このクラスは、システム管理者がユーザの更新トーク ンを取り消した場合の動作を制御します。「Android ネ イティブアプリケーションでの更新トークンの取り消 し処理」を参照してください。 UriFragmentParser この静的ヘルパークラスは直接コールできます。この クラスは、特定の URI を解析して、そのパラメータを 一連のキー/値ペアに分離し、対応付けで返します。 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 は、パスコードワークフローのすべての実装作業を行うわけではありません。パスコード マネージャをコールしてユーザ入力を取得し、パスコードとプレフィックス/サフィックスを組み合わせて、ユー ザデータを暗号化するためのハッシュを作成します。また、パスコードが変更されたときのデータの復号化と再 84 ネイティブ Android の開発 リソースの処理 暗号化を処理します。組織がパスコード要件を変更した場合、Mobile SDK は次のログインで変更を検出し、そ の変更に応じて対応します。パスコードを使用する場合、SalesforceSDKManager.getKey() メソッドを実装 するだけで済みます。この場合、実装で行うべきことは、暗号化キーとして使用できる Base64 エンコード文字 列を返すことだけです。 パスコードは内部的に Base64 エンコード文字列として保存されます。SDK は、Encryptor クラスを使用して、 パスコードからハッシュを作成します。また、パスコードの代わりにキーを入力する場合も、このクラスを使用 してハッシュを生成する必要があります。パスコードとキーは、SmartStore データ、oAuth トークン、ユーザ ID 文字列、関連するセキュリティ情報を暗号化および復号化する場合に使用されます。パスコードで暗号化される セキュリティデータを詳しく確認するには、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 リソースは、native/SalesforceSDK/res フォルダにある XML ファイルで設定されてい ます。これらのリソースの多くは、このフォルダで変更することでカスタマイズできます。 /res フォルダのリソースは、次のようなカテゴリに分類されます。 • Drawables — 背景、影付き、画像リソース (PNG ファイルなど) • Layouts — 可視コンポーネント (パスコード画面など) の画面設定 • Values — SDK で使用される文字列、色、サイズ その他の 2 つのリソース種別は、ほとんど内部で使用されます。 • • Menu XML 85 ネイティブ Android の開発 リソースの処理 drawable、layout、および value リソースは、さまざまなフォーム要素に対応するフォルダにさらに分類されます。 これらのカテゴリは、各種デバイス種別および画面解像度に対応します。各カテゴリはそのフォルダ名で定義さ れるため、すべてのバージョンで同じリソースファイル名を使用できます。たとえば、開発者が icon1.png と いう名前のアイコンをさまざまなサイズで提供する場合、スマートフォン、ローエンドフォン、タブレットに対 応する各フォルダにアイコンを配置します。各フォルダで、このファイル名は icon1.png になります。フォル ダ名の語幹は同じですが、サフィックスが異なります。 次の表に、フォルダ名とサフィックスを示します。 フォルダ名 使用方法 drawable 描画可能リソースの汎用バージョン drawable-hdpi 高解像度 (スマートフォン向け) drawable-ldpi 低解像度 (ローエンド機能端末向け) drawable-mdpi 中解像度 (ローエンド機能スマートフォン) drawable-xhdpi 超高密度画面 (~ 320 dpi) のリソース drawable-xlarge タブレット画面 (横方向) drawable-xlarge-port タブレット画面 (縦方向) drawable-xxhdpi-port 超超高密度画面 (~ 480 dpi) のリソース layout レイアウトの汎用バージョン layout-land 横方向 layout-xlarge タブレット画面 menus [接続を追加] ダイアログおよび電話のログインメニュー values 汎用スタイルおよび値 values-xlarge タブレット画面 xml 一般的なアプリケーション設定 コンパイラは、ターゲットデバイス設定に一致する名前のフォルダでリソースを検索します。要求されたリソー スが想定されるフォルダにない場合 (ターゲットデバイスはタブレットであるが、要求されたアイコンが drawables-xlarge または drawables-xlarge-port フォルダにない場合など)、コンパイラは汎用 drawable フォルダでアイコンファイルを検索します。 Layouts Mobile 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" /> 86 ネイティブ Android の開発 リソースの処理 この場合、EditText コントロールは android:inputType 属性を使用します。その値が「textPassword」となっ ているため、オペレーティングシステムで入力値が隠されます。 style 属性は、リソースの他の場所で定義されたグローバルスタイルを参照します。所定の場所で style 属性を指 定する代わりに、中央ファイルでスタイルを定義し、必要な場所でその属性を参照します。値 @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 フォルダ (タブレットデバイス) にファイルを配置します。 Values res/values および res/values-xlarge フォルダには、サイズ、色、文字列のリソースやカスタムスタイルなどのスタイ ルコンポーネントの定義が含まれています。このフォルダのファイル名は、リソースまたはスタイルコンポーネ ントのタイプを示します。独自の値を提供するには、会社やプロジェクトを反映するファイル名プレフィックス を使用して、同じフォルダに新しいファイルを作成します。たとえば、開発者のプレフィックスが XYZ の場合、 XYZ__styles.xml という名前の新しいファイルで sf__styles.xml を上書きできます。 ファイル名 次の文字列を含む sf__colors.xml Mobile SDK スタイルで参照される色 sf__dimens.xml Mobile SDK スタイルで参照されるサイズ sf__strings.xml Mobile SDK スタイルで参照される文字列。エラーメッセージを 上書きできます。 sf__styles.xml Mobile SDK で使用されるビジュアルスタイル strings.xml アプリケーション定義の文字列 strings.xml の値を上書きできます。ただし、create_native スクリプトを使用してアプリケーションを作成 した場合、strings.xml の文字列はすでに適切な値を反映しています。 その他のリソース その他の 2 つのフォルダには、Mobile SDK リソースが含まれています。 • res/menu は、内部的に使用されるメニューを定義します。アプリケーションで新しいメニューを定義する場 合、新しいファイルのこの場所にリソースとして追加します。 • res/xml には、編集する必要のあるファイル servers.xml が含まれています。このファイルでは、デフォル トの本番サーバおよび Sandbox サーバを組織のログインサーバに変更する必要があります。このフォルダに 87 ネイティブ Android の開発 REST API の使用 あるその他のファイルは内部で使用されます。authenticator.xml ファイルはアカウント認証リソースを設 定し、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 プラミングをカプセル化します。これらのクラスには、以下が含まれます。 • ClientManager — RestClient インスタンスのファクトリとして機能します。また、アカウントログインや Salesforce サーバとのハンドシェイクも処理します。Mobile SDK によって実装されます。 • RestClient — REST API 要求を Salesforce サーバに送信するためのプロトコルを処理します。RestClient のインスタンスを直接作成しないでください。代わりに、ClientManager.getRestClient() メソッドをコー ルします。Mobile SDK によって実装されます。 • RestRequest — アプリケーションから提供されるデータに基づいて REST API 要求を書式設定します。ま た、自身のインスタンスのファクトリとしても機能します。RestRequest のインスタンスを直接作成しない でください。代わりに、適切な RestRequest の静的 getter 関数 (RestRequest.getRequestForCreate() な ど) をコールします。SDK によって実装されます。 • RestResponse — 要求された書式で応答コンテンツを書式設定して、書式設定した応答をアプリケーション に返し、コンテンツストリームを終了します。RestRequest クラスは、RestResponse のインスタンスを作 成し、RestClient.AsyncRequestCallback インターフェースの実装を介してアプリケーションに返しま す。SDK によって実装されます。 RestRequest クラスは、Salesforce REST および SOAP API によって提供される標準の Salesforce データ操作をネ イティブに処理します。サポートされる操作は次のとおりです。 操作 パラメータ 説明 Versions なし Salesforce バージョンのメタデータを 返します。 Resources API バージョン リソース名および URI を含む、指定 された API バージョンで使用可能な リソースを返します。 Metadata API バージョン、オブジェクト種別 88 ネイティブ Android の開発 REST API の使用 操作 パラメータ 説明 DescribeGlobal API バージョン 組織で使用できるすべてのオブジェ クトとそのメタデータのリストを返 します。 Describe API バージョン、オブジェクト種別 1 つのオブジェクト種別の説明を返 します。 Create API バージョン、オブジェクト種 指定したオブジェクトに新しいレ 別、値オブジェクトに対する項目名 コードを作成します。 の対応付け Retrieve API バージョン、オブジェクト種 オブジェクト ID でレコードを取得 別、オブジェクト ID、項目のリスト します。 Update API バージョン、オブジェクト種 指定された対応付けでオブジェクト 別、オブジェクト ID、値オブジェク を更新します。 トに対する項目名の対応付け Upsert API バージョン、オブジェクト種 外部 ID が外部 ID 項目に現在存在し 別、外部 ID 項目、外部 ID、値オブ ているかどうかに基づいて、外部 ジェクトに対する項目名の対応付け データからオブジェクトを更新また は挿入します。 Delete API バージョン、オブジェクト種 別、オブジェクト ID 指定された ID を持つ特定のタイプ のオブジェクトを削除します。 適切な RestRequest インスタンスを取得するには、実行する操作に一致する RestRequest 静的メソッドをコー ルします。次に、RestRequest 静的メソッドを示します。 • • • • • • • • • • • • getRequestForCreate() getRequestForDelete() getRequestForDescribe() getRequestForDescribeGlobal() getRequestForMetadata() getRequestForQuery() getRequestForResources() getRequestForRetrieve() getRequestForSearch() getRequestForUpdate() getRequestForUpsert() getRequestForVersions() これらのメソッドは、RestClient のインスタンスに渡す RestRequest オブジェクトを返します。RestClient クラスは、要求を送信する同期メソッド (sendSync()) および非同期メソッド (sendAsync()) を提供します。UI スレッドから要求を送信する場合は、sendAsync() を使用します。 sendSync() は、非 UI スレッド (アクティ ビティによって実行されるサービスまたはワーカースレッドなど) の場合にのみ使用します。 次に、UI スレッドで REST クラスを使用する場合の基本手順を示します。 89 ネイティブ Android の開発 REST API の使用 1. ClientManager のインスタンスを作成します。 a. SalesforceSDKManager.getInstance().getAccountType() メソッドを使用して、ClientManager コ ンストラクタの第 2 引数として渡す値を取得します。 b. ClientManager コンストラクタの LoginOptions パラメータの場合、 SalesforceSDKManager.GetInstance().getLoginOptions() をコールします。 2. ClientManager.RestClientCallback インターフェースを実装します。 3. ClientManager.getRestClient() をコールして RestClient インスタンスを取得し、RestClientCallback 実装のインスタンスに渡します。native/SampleApps/RestExplorer サンプルアプリケーションの次のコー ドは、RestClientCallback をインラインで実装およびインスタンス化しています。 String accountType = SalesforceSDKManager.getInstance().getAccountType(); LoginOptions loginOptions = SalesforceSDKManager.getInstance().getLoginOptions(); // Get a rest client new ClientManager(this, accountType, loginOptions, SalesforceSDKManager.getInstance().shouldLogoutWhenTokenRevoked()).getRestClient(this, new RestClientCallback() { @Override public void authenticatedRestClient(RestClient client) { if (client == null) { SalesforceSDKManager.getInstance().logout(ExplorerActivity.this); return; } // Cache the returned client ExplorerActivity.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(); @Override public void onSuccess(RestRequest request, RestResponse result) { try { // Do something with the result } catch (Exception e) { printException(e); 90 ネイティブ Android の開発 Android テンプレートアプリケーション: 詳細 } EventsObservable.get().notifyEvent(EventType.RenditionComplete); } @Override public void onError(Exception exception) { printException(exception); EventsObservable.get().notifyEvent(EventType.RenditionComplete); } }); サービスから sendSync() メソッドをコールする場合、次の点を変更して同じ手順を実行します。 1. RestClient インスタンスを取得するには、ClientManager.getRestClient() ではなく ClientManager.peekRestClient() をコールします。 2. sendSync() メソッドの戻り値から、書式設定された REST 応答を取得します。 Android テンプレートアプリケーション: 詳細 TemplateApp サンプルプロジェクトは、基本的な Android アプリケーションの作成に必要なすべてを実装しま す。これは「ベアボーン」サンプルであるため、Mobile SDK の create_native ant スクリプトで新しいネイティブ Android プロジェクトを設定するために使用するテンプレートとしても機能します。このプロジェクトを学習す れば、ネイティブ Android SDK を迅速に理解できます。 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 のインスタンスが必要です。次 に、クラス全体を示します。 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 { @Override public void onCreate() { 91 ネイティブ Android の開発 MainActivity クラス super.onCreate(); SalesforceSDKManager.initNative(getApplicationContext(), new KeyImpl(), MainActivity.class); } } TemplateApp クラスは、次の 2 つの主要なタスクを実行します。 • initNative() をコールしてアプリケーションを初期化する • KeyInterface のアプリケーションの実装を渡す 大部分のネイティブ Android アプリケーションは同じようなコードを使用できます。このわずかな作業で、アプ リケーションはパスコードおよびログイン/ログアウトメカニズムを自由に実装でき、その他のいくつかの利点 も得られます。「SalesforceActivity クラス、SalesforceListActivity クラス、および SalesforceExpandableListActivity クラス」を参照してください。 MainActivity クラス Mobile SDK アプリケーションでは、メインアクティビティはユーザのログイン直後に始まります。メインアク ティビティが実行されると、他のアクティビティを起動できるようになり、次にサブアクティビティを起動でき るようになります。メインアクティビティを終了することで、アプリケーションが終了します。他のすべてのア クティビティは、メインアクティビティ内で連鎖的に終了します。 テンプレートアプリケーションの MainActivity クラスは、 com.salesforce.androidsdk.ui.sfnative.SalesforceActivity を拡張します。このスーパークラスは、 Mobile SDK の基本抽象アクティビティクラス SalesforceActivity で、必須のパスコードおよびログインプロ トコルを自由に実装できます。代わりに別の基本アクティビティクラスを使用する場合、これらのプロトコルを 自分で実装する必要があります。MainActivity は、アプリケーションの UI を初期化してその UI ボタンを実装 します。UI には、ユーザの Salesforce 取引先責任者または取引先を表示できるリストビューも含まれます。ユー ザがこれらのいずれかのボタンをクリックすると、MainActivity オブジェクトが数個の基本クエリを実行し て、ビューを作成します。たとえば、Salesforce からユーザの取引先責任者を取得する場合、 onFetchContactsClick() メッセージハンドラが次のような単純な SOQL クエリを送信します。 public void onFetchContactsClick(View v) throws UnsupportedEncodingException { sendRequest("SELECT Name FROM Contact"); } 内部的には、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() { @Override public void onSuccess(RestRequest request, RestResponse result) { try { listAdapter.clear(); JSONArray records = result.asJSONObject().getJSONArray("records"); for (int i = 0; i < records.length(); i++) { 92 ネイティブ Android の開発 TemplateApp マニフェスト listAdapter.add(records.getJSONObject(i).getString("Name")); } } catch (Exception e) { onError(e); } } @Override public 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 リストのコントロールを設定します。クエリに失敗した場合、 コールバックオブジェクトはトーストポップアップでエラーメッセージを表示します。 Java に関する注意事項: RestClient.sendAsync() をコールするコードで、新しい AsyncRequestCallback オブジェクトをその第 2 引 数としてインスタンス化します。ただし、AsyncRequestCallbackconstructor の後に、いくつかのメソッド (onSuccess() や onError()) より優先されるコードブロックが続きます。このコードに不自然な点がある場合、 よく状況を確認してください。ASyncRequestCallback は、インターフェースとして定義されるため、実装は ありません。これをインスタンス化するために、コードで 2 つの ASyncRequestCallback メソッドをインライ ンで実装して、匿名クラスオブジェクトを作成します。この手法により、別のオブジェクトからコールされない 独自の sendAsync() 実装を TemplateApp に提供でき、一連の特殊なクラス名で API が見づらくなることもあ りません。 TemplateApp マニフェスト TemplateApp プロジェクトの AndroidManifest.xml ファイルを見ると、Mobile SDK ネイティブ Android アプ リケーションに必要なコンポーネントがわかります。次のコンポーネントのみ必要になります。 名前 タイプ MainActivity アクティビ ログイン後にコールさ ティ れる最初のアクティビ ティ。名前とクラスは プロジェクトで定義さ れます。 93 説明 ネイティブ Android の開発 チュートリアル: ネイティブ Android Warehouse アプリ ケーションの作成 create_native スクリプトで作成されたアプリケーションは、TemplateApp プロジェクトに基づいているため、 MainActivity コンポーネントはすでにそのマニフェストに含まれています。他の Android アプリケーションと 同様に、Eclipse の Android マニフェストエディタを使用して、他のコンポーネント (カスタムアクティビティま たはサービスなど) を追加できます。 チュートリアル: ネイティブ Android Warehouse アプリケーショ ンの作成 モバイル在庫管理アプリケーションを構築することで、ネイティブ Android SDK の知識を応用します。このチュー トリアルでは、2 つのアクティビティを定義する簡単な主従関係アーキテクチャについて説明します。また、 Mobile SDK アプリケーションの設定、REST API ラッパークラスの使用、および Android SDK のインテグレー ションについても説明します。 前提条件 このチュートリアルでは、次のツールおよびパッケージが必要になります。 • このチュートリアルでは、基本的な在庫データベースを含む Warehouse アプリケーションを使用します。こ のアプリケーションを DE 組織にインストールする必要があります。既存の DE 組織にインストールする場 合、作成した既存の Warehouse コンポーネントをすべて削除してからインストールしてください。 1. インストール用 URL リンク https://login.salesforce.com/packaging/installPackage.apexp?p0=04ti0000000MMMT をクリックします。 2. すでにログインしている場合は、DE 組織のユーザ名とパスワードを入力します。 3. [パッケージインストールの詳細] ページで、[次へ] をクリックします。 4. [次へ] をクリックし、[Security Level (セキュリティレベル)] ページで [Next (次へ)] をクリックします。 5. [インストール] をクリックします。 6. [Deploy Now (今すぐデプロイ)] をクリックしてから、[Deploy (デプロイ)] をクリックします。 7. インストールが完了したら、右上のアプリケーションピッカーから [Warehouse (倉庫)] アプリケーション を選択できます。 8. データを作成するには、[Data (データ)] タブをクリックします。 9. [Create Data (データを作成)] ボタンをクリックします。 • 次の最新バージョンをインストールします。 ◊ Java JDK 6 以降 — http://www.oracle.com/downloads。 ◊ Apache Ant 1.8 以降 — http://ant.apache.org。 94 ネイティブ Android の開発 ネイティブ Android アプリケーションを作成する ◊ Android SDK Tools バージョン 21 以降 —http://developer.android.com/sdk/installing.html。 メモ: 最良の結果を得るには、対象バージョンだけでなく、Android SDK の以前のすべてのバー ジョンもインストールします。 ◊ Eclipse — https://www.eclipse.org。サポートされている Eclipse の最小バージョンについては、Android 開発ツールに関する Web サイトを参照してください。 ◊ Eclipse バージョン 21 以降用の Android ADT (Android 開発ツール) プラグイン — http://developer.android.com/sdk。 ◊ アプリケーションをエミュレータで実行するには、Platform 2.2 以降 (4.0 以降を推奨) を対象とする Android 仮想デバイス (AVD) を少なくとも 1 つ設定する必要があります。Eclipse での AVD の設定方法について は、http://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 で接続アプリケーションを設定する方法を学習します。これを行うことで構築す るモバイルアプリケーションが認証され、ユーザの代わりに業界標準の OAuth 2.0 プロトコルを介して Force.com と安全に通信し、Force.com API にアクセスできるようになります。 95 ネイティブ Android の開発 ステップ 2: ネイティブ Android プロジェクトを作成す る 1. DE 組織で、あなたの名前 > [設定] をクリックし、[作成] > [アプリケーション] をクリックします。 2. [接続アプリケーション] で、[新規] をクリックして、[新規接続アプリケーション] ページを表示します。 3. [基本情報] で、フォームに次のように入力します。 • 接続アプリケーション名: My Native Android App (私のネイティブ Android アプリケーション) • API 参照名: 推奨値を受け入れます。 • 取引先責任者 メール: メールアドレスを入力します。 4. OAuth 設定で、[OAuth 設定の有効化] チェックボックスをオンにします。 5. [コールバック URL] を mysampleapp://auth/success に設定します。 6. [利用可能な OAuth 範囲] で、[データへのアクセスと管理] (api) および [ユーザに代わっていつでも要求を実 行] (refresh_token) をオンにして、[追加] をクリックします。 7. [保存] をクリックします。 設定を保存すると、作成した接続アプリケーションの詳細が表示されます。 • コールバック URL およびコンシューマ鍵を記録します。これらは、次のステップでネイティブアプリケー ションを設定するときに使用します。 • モバイルアプリケーションではコンシューマの秘密は使用しないため、この値は無視できます。 ステップ 2: ネイティブ Android プロジェクトを作成する 新しい Mobile SDK プロジェクトを作成するには、ターミナルウィンドウで forcedroid ユーティリティをもう一 度使用します。 1. プロジェクトを作成するディレクトリに変更します。 2. Android プロジェクトを作成するには、「forcedroid create」と入力します。 設定値ごとに、forcedroid ユーティリティによってプロンプトが表示されます。 3. アプリケーション種別に、「native」と入力します。 4. アプリケーション名に、Warehouse と入力します。 5. ターゲットディレクトリに、「tutorial/AndroidNative」と入力します。 6. パッケージ名に、「com.samples.warehouse」と入力します。 7. SmartStore を使用するかどうか確認を求められたら、[Return] キーを押して、デフォルトを受け入れます。 96 ネイティブ Android の開発 ステップ 3: 新しい Android アプリケーションを実行す る ステップ 3: 新しい Android アプリケーションを実行する これで、新しい Android アプリケーションが正常に作成されたので、Eclipse でそれを構築して実行し、環境が適 切に設定されていることを確認します。 メモ: 問題が発生したら、まず Android SDK マネージャをチェックして、最新の Android SDK、ビルド ツール、および開発ツールを取得していることを確認します。Android SDK マネージャは、Eclipse の [Window (ウィンドウ)] > [Android SDK Manager] にあります。欠落しているもののすべてをインストー ルしたら、Android SDK マネージャを終了して再起動し、確実に最新の状態にします。 Eclipse でのアプリケーションのインポートおよび作成 forcedroid スクリプトにより、Eclipse エディタで新しいアプリケーションを実行する手順が出力されます。 1. Eclipse を起動し、ワークスペースディレクトリとして tutorial/AndroidNative を選択します。 2. [Eclipse] > [Preferences (個人設定)] を選択し、[Android] セクションを選択して、Android SDK の場所を入力 します。 3. [OK] をクリックします。 4. [File (ファイル)] > [Import (インポート)] を選択し、[General (一般)] > [Existing Projects into Workspace (既存の プロジェクトをワークスペースへ)] を選択します。 5. [Next (次へ)] をクリックします。 6. ルートディレクトリとして forcedroid/native ディレクトリを指定します。表示されるリストの横にある [すべて選択解除] をクリックし、リストを参照して SalesforceSDK プロジェクトにチェックを入れます。 7. [完了] をクリックします。 8. ステップ 4 ~ 8 を繰り返します。ステップ 6 で、tutorial/AndroidNative をルートとして選択し、新しい Warehouse プロジェクトのみを選択します。 プロジェクトのインポートが完了したら、Eclipse によって自動的にワークスペースが作成されます。このプロセ スには数分かかる場合があります。ステータスバーにエラーが表示されていなければ、プロジェクトを実行でき ます。 1. Eclipse ワークスペースで、Ctrl キーを押しながらプロジェクトをクリックするか、プロジェクトを右クリッ クします。 2. ポップアップメニューから、[Run As (別のユーザとして実行)] > [Android Application (Android アプリケーショ ン)] を選択します。 メモ: [別のユーザとして実行] メニューに [Android アプリケーション] が表示されていない場合、 Android エミュレータまたはデバイスを設定する必要があります。 Eclipse によってエミュレータまたは接続されている Android デバイスでアプリケーションが起動します。 ステップ 4: Android アプリケーションの仕組みを探索する ネイティブ Android アプリケーションは、簡単な Model View Controller (MVC) アーキテクチャを使用します。 97 ネイティブ Android の開発 ステップ 4: Android アプリケーションの仕組みを探索す る • モデルは、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 を使用して要求を発行し、メインアク ティビティで応答を表示するだけです。このチュートリアルでは、テンプレートアプリケーションのコントロー ルを置き換えて、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 ファイルの接続アプリケーション情報を使用します。 98 ネイティブ Android の開発 リスト画面をカスタマイズする リスト画面をカスタマイズする このチュートリアルでは、メインアクティビティとそのレイアウトを修正し、Warehouse スキーマ固有のアプリ ケーションを作成します。また、Merchandise カスタムオブジェクトから必要なすべての情報を取得できるよう に、既存の SOQL クエリを適合させます。 ステップ 1: 既存のコントロールを削除する テンプレートコードで提供されるメインアクティビティ画面は、目的に合っていません。コード用の領域を確保 しましょう。 1. Eclipse の Package Explorer から、res/layout/main.xml ファイルを開きます。ビューをテキスト形式モード に設定してください。この XML ファイルには <LinearLayout> ルートノードがあり、このルートノードに は、<include> ノード、ネストされた <LinearLayout> ノード、および <ListView> ノードの 3 つの子ノー ドが含まれています。 2. 3 つの <Button> ノードがある、ネストされた <LinearLayout> ノードを削除します。編集したファイルは 次のようになります。 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#454545" android:id="@+id/root"> <include layout="@layout/header" /> <ListView android:id="@+id/contacts_list" android:layout_width="fill_parent" android:layout_height="fill_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 ブロックを追加します。 99 ネイティブ Android の開発 ステップ 2: SOQL クエリを更新する 2. Merchandise__c カスタムオブジェクトから最大 10 個のレコードを返すハードコード化された SOQL クエ リを追加します。 private void fetchDataForList() { String soql = "SELECT Name, Id, Price__c, Quantity__c FROM Merchandise__c LIMIT 10"; 3. RestRequest.getRequestForQuery() へのコールを try...catch ブロックで囲みます。置換前のステート メントは、次のとおりです。 RestRequest restRequest = RestRequest.getRequestForQuery(getString(R.string.api_version), soql); 置換後 RestRequest restRequest = null; try { 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 FROM Merchandise__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() { @Override public 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); } } @Override public void onError(Exception exception) { Toast.makeText(MainActivity.this, MainActivity.this.getString( SalesforceSDKManager.getInstance(). 100 ネイティブ Android の開発 ステップ 3: アプリケーションを試す getSalesforceR().stringGenericError(), exception.toString()), Toast.LENGTH_LONG).show(); } }); } 画面が読み込まれて認証が完了したら、fetchDataForList() をコールします。 4. onResume(RestClient client) メソッドで、メソッド本文の最後に次の行を追加します。 @Override public void onResume(RestClient client) { // Keeping reference to rest client this.client = client; // Show everything findViewById(R.id.root).setVisibility(View.VISIBLE); // Fetch data for list fetchDataForList(); } 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: アプリケーションを試す アプリケーションをテストするには、Package Explorer で Ctrl キーを押しながらアプリケーションをクリックし、 [Run As (別のユーザとして実行)] > [Android Application (Android アプリケーション)] を選択します。Android エ ミュレータが表示されたら、読み込みが完了するまで数分待機します。画面のロックを解除して、Salesforce ログ イン画面が表示されるまでもうしばらく待機します。Salesforce に正常にログインできたら、[許可] をクリックし て必要な権限をアプリケーションに付与します。 この時点で Merchandise レコードをクリックしても何も起きません。次のチュートリアルでこれを修正します。 101 ネイティブ Android の開発 詳細画面を作成する 詳細画面を作成する 前のステップで、メインアクティビティで最大 10 個の Merchandise レコードのリストを表示するようにテンプ レートアプリケーションを変更しました。このステップでは、詳細アクティビティおよびレイアウトを作成して 作業を終了します。次に、メインアクティビティと詳細アクティビティをリンクします。 ステップ 1: 詳細画面を作成する まず、res/layout/detail.xml という名前の XML ファイルを作成して詳細アクティビティのレイアウトを設 計します。 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="fill_parent" android:layout_height="fill_parent" android:background="#454545" android:orientation="vertical" > <include layout="@layout/header" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/name_label" android:width="100dp" /> <EditText android:id="@+id/name_field" android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="text" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView 102 ネイティブ Android の開発 ステップ 1: 詳細画面を作成する android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/price_label" android:width="100dp" /> <EditText android:id="@+id/price_field" android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/quantity_label" android:width="100dp" /> <EditText android:id="@+id/quantity_field" android:layout_width="fill_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> 後で追加するボタンを除き、詳細画面のレイアウトおよび文字列リソースの設計は完了しました。画面の動作を 実装するには、新しいアクティビティを定義します。 103 ネイティブ Android の開発 ステップ 2: DetailActivity クラスを作成する ステップ 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() メソッド本文で、次のコードを追加します。 @Override public void onResume(RestClient client) { // Keeping reference to rest client this.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; 104 ネイティブ Android の開発 ステップ 4: 2 つのアクティビティをリンクする - 第 1 部: データクラスを作成する 3. Merchandise カスタムオブジェクトのレコード ID を格納する変数を追加します。後でメインアクティビティ と詳細アクティビティをリンクするときに、この変数を入力するコードを追加します。 private String merchandiseId; 4. 作成した detail.xml レイアウトを使用するようにビューを設定する onCreate() メソッドを追加します。 このメソッドをクラス定義の最後の直前に配置します。 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Setup view setContentView(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; } } 105 ネイティブ Android の開発 ステップ 5: 2 つのアクティビティをリンクする - 第 2 部: リスト項目クリックハンドラを実装する 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 { 106 ネイティブ Android の開発 ステップ 5: 2 つのアクティビティをリンクする - 第 2 部: リスト項目クリックハンドラを実装する 4. このリストビューの非公開メンバーを追加します。 private ListView listView; 5. super.onResume() コールの直前の onResume() メソッドに次の太字のコードを追加します。 public void onResume() { // Hide everything until we are logged in findViewById(R.id.root).setVisibility(View.INVISIBLE); // Create list adapter listAdapter = 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 view listView = (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 クラスを更新して、終了しましょう。 107 ネイティブ Android の開発 ステップ 6: [更新] ボタンを実装する 10. Package Explorer で、[src] > [com.samples.warehouse] > [DetailActivity.java] を開きます。 11. onCreate() メソッドで、リスト画面の選択値を詳細アクティビティの対応するデータメンバーに割り当てま す。 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Setup view setContentView(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 intent Bundle 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="fill_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 値と一致している必要があります。この場 合、名前は onUpdateClick です。このメソッドは単に、Merchandise__c 項目名をそれに対応する詳細画面 の値と照合する対応付けを作成します。値が設定されると、saveData() メソッドをコールして、変更内容を サーバに書き込みます。 108 ネイティブ Android の開発 ステップ 6: [更新] ボタンを実装する 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 user return; } client.sendAsync(restRequest, new RestClient.AsyncRequestCallback() { @Override public 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 } } @Override public void onError(Exception e) { // You might want to log the error or show it to the user } }); } これで完成です。アプリケーションを実行してテストする準備ができました。 109 ネイティブ Android の開発 ステップ 7: アプリケーションを試す ステップ 7: アプリケーションを試す 1. アプリケーションを構築し、Android エミュレータで実行します。すべて適切に行った場合、Warehouse 画面 の Merchandise レコードをクリックしたときに詳細ページが表示されます。 2. レコードの数量と価格を更新します。値を編集した後で詳細ビューの [更新] ボタンをクリックしてください。 詳細ビューに戻ると、更新された値が表示されます。 3. DE 組織にログインして、ブラウザ UI でレコードを表示し、更新された値を確認します。 Android ネイティブサンプルアプリケーション Salesforce Mobile SDK には、次のネイティブ Android サンプルアプリケーションがあります。 • RestExplorer: SalesforceSDK の OAuth および REST API 機能を示します。また、REST API アクションを Honeycomb タブレットから調べる場合にも便利です。 1. Eclipse ワークスペースからアプリケーションを実行するには、[RestExplorer] プロジェクトを右クリック し、[Run As (別のユーザとして実行)] > [Android Application (Android アプリケーション)] を選択します。 2. テストを実行するには、[RestExplorerTest] プロジェクトを右クリックし、[Run As (別のユーザとして実 行)] > [Android JUnit Test (Android JUnit テスト)] を選択します。 • NativeSqlAggregator: SQL と SmartSQL の統合を示します。また、そのようなアプリケーションとして SmartStore のネイティブ実装の方法も示します。Eclipse ワークスペースからアプリケーションを実行するには、 [NativeSqlAggregator] プロジェクトを右クリックし、[Run As (別のユーザとして実行)] > [Android Application (Android アプリケーション)] を選択します。 • FileExplorer: Files API および基盤となる Google Volley のネットワーキングの機能強化を示します。Eclipse ワークスペースからアプリケーションを実行するには、[FileExplorer] プロジェクトを右クリックし、[Run As (別のユーザとして実行)] > [Android Application (Android アプリケーション)] を選択します。 110 第7章 ハイブリッド開発の概要 トピック: • • • • • • • ハイブリッド開発について iOS のハイブリッド開発 Android のハイブリッド開発 ハイブリッドアプリケーションの JavaScript ファイル バージョン設定および JavaScript ライブラリの互換性 ハイブリッドアプリケーションで のセッション管理 例: 適切な JavaScript ライブラリの 提供 ハイブリッドアプリケーションは、HTML5 Web アプリケーションの 開発の容易さと、ネイティブプラットフォームの機能とを統合したもの です。これらは、Salesforce Mobile コンテナ (アプリケーションをデバ イス固有のコードに変換するネイティブレイヤ) 内で実行されます。 ハイブリッドアプリケーションは、HTML ファイルと JavaScript ファ イルに依存します。これらのファイルは、デバイスまたはサーバに保 存できます。 • デバイス — forcetk.mobilesdk.js ライブラリで開発されたハイ ブリッドアプリケーションは、Salesforce Mobile コンテナ内で Web アプリケーションをラップします。この場合、JavaScript ファイル と HTML ファイルがデバイスに保存されます。 • サーバ — Visualforce テクノロジを使用して開発されたハイブリッ ドアプリケーションでは、HTML ファイルと JavaScript ファイルが Salesforce サーバに保存され、Salesforce Mobile コンテナを通して提 供されます。 他の開発者が使用するためにライブラリまたはサンプルアプリケーショ ンを作成している場合は、GitHub などのバージョン管理されるオンラ インリポジトリに公開モジュールを投稿することをお勧めします (https://github.com)。スニペットなどの小規模なサンプル用に、GitHub にはオーバーヘッドの低い共有フォーラムである gist が用意されてい ます (https://gist.github.com)。 111 ハイブリッド開発の概要 ハイブリッド開発について ハイブリッド開発について ハイブリッドアプリケーションを Mobile SDK コンテナで開発する場合、すべての変更の作成/リリース手順が必 要になります。JavaScript 開発は、ブラウザで行う方が作成/コンパイル手順がないため簡単です。この理由によ り、ハイブリッドアプリケーションはブラウザで直接開発し、テストの最終段階でのみコンテナでコードを実行 することをお勧めします。コードに変更を加えるたびに、ブラウザを更新して変更内容を確認できます。 開発者ツールが組み込まれている Google Chrome などのブラウザで開発することをお勧めします。これらのツー ルでは、実行時に Web アプリケーションのシンボルおよびコードにアクセスできます。 iOS のハイブリッド開発 ハイブリッドアプリケーションを開発するには、iOS ネイティブおよび標準の HTML5 シナリオの両方が一部の 前提条件を満たしている必要があります。 1. HTML5 開発 の要件を満たしていることを確認します。 2. iOS のインストール手順に従います。 3. Mobile SDK for iOS をインストールしたら、「iOS プロジェクトの作成」 で説明されているように新しいハ イブリッドアプリケーションを作成します。apptype パラメータでは、以下を使用します。 • -—apptype=”hybrid_local” (ローカルプロジェクトのすべてのコードを含むハイブリッドアプリケーショ ンの場合)。HTML および JavaScript ファイルを ${target.dir}/assets/www/ に配置します。 • -—apptype=”hybrid_remote” (サーバの Visualforce アプリケーションのコードを含むハイブリッドアプ リケーションの場合) iOS ハイブリッドサンプルアプリケーション HybridShared/SampleApps フォルダに含まれているサンプルアプリケーションは、PhoneGap SDK を対象に設 計されています。PhoneGap は Cordova とも呼ばれます。Salesforce Mobile SDK バージョン 1.4 以降では Cordova ライブラリが含まれているため、別途インストールは必要ありません。Cordova SDK のドキュメントについて は、『Getting Started Guide』を参照してください。 hybrid/SampleApps フォルダには、次のサンプルプロジェクトがあります。 • AccountEditor: SmartSync Data Framework を使用して Salesforce データにアクセスする方法について説明しま す。 • HybridFileExplorer: Files API を示します。 • ContactExplorer: ContactExplorer サンプルアプリケーションでは、PhoneGap (Cordova とも呼ばれる) を使 用して、ローカルデバイスの取引先責任者を取得します。また、forcetk.mobilesdk.js ツールキットを使 用して、Salesforce REST API で REST トランザクションを実装します。アプリケーションでは、Salesforce SDK の OAuth2 サポートを使用して OAuth ログイン情報を取得し、JavaScript イベントを送信することによっ て、そのログイン情報を forcetk.mobilesdk.js に伝搬します。 • VFConnector: ネイティブコンテナ内の Visualforce ページのラップ方法を示す VFConnector サンプルアプリ ケーションです。この例では、BasicVFTest という Visualforce ページが組織に存在することを想定していま す。アプリケーションではまず、Salesforce SDK OAuth2 サポートを使用して OAuth のログイン情報を取得 112 ハイブリッド開発の概要 Android のハイブリッド開発 し、そのログイン情報を使用して、Visualforce ページにアクセスするための適切な Web ビュー Cookie を設定 します。 • SmartStoreExplorer: SmartStore API を探索できます。 Android のハイブリッド開発 ハイブリッドアプリケーションを開発するには、Android ネイティブおよびプレーン HTML5 の両方のシナリオ が一部の前提条件を満たしている必要があります。 1. HTML5 開発 の要件を満たしていることを確認します。 2. Android ネイティブのインストール手順に従います。 3. Mobile SDK for Android をインストールしたら、「Android プロジェクトの作成」 で説明されているように新 しいハイブリッドアプリケーションを作成します。apptype パラメータでは、以下を使用します。 • -—apptype=”hybrid_local” (ローカルプロジェクトのすべてのコードを含むハイブリッドアプリケーショ ンの場合)。HTML および JavaScript ファイルを ${target.dir}/assets/www/ に配置します。 • -—apptype=”hybrid_remote” (サーバの Visualforce アプリケーションのコードを含むハイブリッドアプ リケーションの場合) Android ハイブリッドサンプルアプリケーション ./hybrid フォルダには、サンプルプロジェクトおよび関連するテストアプリケーションがあります。 • AccountEditor: SmartSync Data Framework を使用して Salesforce データにアクセスする方法について説明しま す。 • SampleApps/HybridFileExplorer: Files API を示します。 • SampleApps/ContactExplorer: ContactExplorer サンプルアプリケーションでは、PhoneGap (Cordova とも呼 ばれる) を使用して、ローカルデバイスの取引先責任者を取得します。また、forcetk.mobilesdk.js ツー ルキットを使用して、Salesforce REST API で REST トランザクションを実装します。アプリケーションでは、 Salesforce SDK の OAuth2 サポートを使用して OAuth ログイン情報を取得し、JavasScript イベントを送信する ことによって、そのログイン情報を forcetk.mobilesdk.js に伝搬します。 • SampleApps/test/ContactExplorerTest: ContactExplorer サンプルアプリケーションをテストします。 • SampleApps/VFConnector: ネイティブコンテナ内の Visualforce ページのラップ方法を示す VFConnector サン プルアプリケーションです。この例では、BasicVFTest という Visualforce ページが組織に存在することを想 定しています。アプリケーションではまず、Salesforce SDK OAuth2 サポートを使用して OAuth のログイン情 報を取得し、そのログイン情報を使用して、Visualforce ページにアクセスするための適切な Web ビュー Cookie を設定します。 • SampleApps/test/VFConnectorTest: VFConnector サンプルアプリケーションをテストします。 • SampleApps/SmartStoreExplorer: SmartStore API を探索できます。 • SampleApps/test/SmartStoreExplorerTest: SmartStoreExplorer サンプルアプリケーションをテストします。 113 ハイブリッド開発の概要 ハイブリッドアプリケーションの JavaScript ファイル ハイブリッドアプリケーションの JavaScript ファイル Salesforce Mobile SDK 2.0 では、SmartSync をサポートできるように、一部の JavaScript ファイルを再構成して新 しいファイルを追加しました。JavaScript ファイルは、GitHub の forcedotcom/SalesforceMobileSDK-Shared リポジトリにあります。 再構成された JavaScript ファイル cordova.force.js ファイルで次のファイルが収集されるようになりました。 • • • SFHybridApp.js SalesforceOAuthPlugin.js SmartStorePlugin.js 新しい JavaScript ファイル Mobile SDK 2.0 の新しいファイルは、次のとおりです。 JavaScript ファイル 説明 cordova.force.js Cordova ライブラリを使用するハイブリッドアプリケー ションのプラグインを格納する SmartSync.js SmartSync Data Framework ライブラリ 新しい外部連動関係 Mobile SDK 2.0 では、新しい外部連動関係が導入されています。 外部 JavaScript ファイル 説明 jquery.js 一般的な HTML ユーティリティライブラリ underscore.js SmartSync サポート backbone.js SmartSync サポート 含める JavaScript ファイル 含めるファイルは、ハイブリッドプロジェクトのタイプによって異なります。次に示す各タイプのリストのファ イルをすべて含めます。 基本的なハイブリッドアプリケーションの場合: • • cordova.js cordova.force.js 基本的なハイブリッドアプリケーションから REST API コールを行う場合: • • • cordova.js cordova.force.js forcetk.mobilesdk.js ハイブリッドアプリケーションで SmartSync を使用する場合: 114 ハイブリッド開発の概要 • • • • • • • バージョン設定および JavaScript ライブラリの互換性 jquery.js underscore.js backbone.js cordova.js cordova.force.js forcetk.mobilesdk.js SmartSync.js バージョン設定および JavaScript ライブラリの互換性 ハイブリッドアプリケーションでは、クライアント JavaScript コードは、Cordova (以前の PhoneGap) および SalesforceSDK プラグインを通してネイティブコードとやり取りします。JavaScript コードをモバイルアプリケー ションとパッケージ化する場合は、テストによって JavaScript コードがネイティブコードで動作することを確認 します。ただし、アプリケーションが VisualForce で記述されている場合など、JavaScript コードがサーバから取 得される場合は、有害な競合が発生する可能性があります。このような場合は、使用している Mobile SDK とバー ジョンが一致する PhoneGap または 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 コードで、ネイティブコンポーネントには Javascript ライブラリの Cordova 1.8.1 および Mobile SDK 1.3 バージョンを通じてのみアクセスする必要がありま す。バージョンが一致しない JavaScript ライブラリを使用すると、アプリケーションがクラッシュする可能性が あります。 クライアントのアップグレードを顧客に強制することはできないため、どのようにすればクラッシュを回避でき るのでしょうか。まず、クライアントのバージョンを識別します。次に、クライアントが古い場合にはアプリ ケーションへのアクセスを拒否する (「最新バージョンに更新してください」警告など) か、互換性のある JavaScript ライブラリを提供 (推奨) します。 次の表に、Cordova および PhoneGap のバージョンと Mobile SDK バージョンの相関付けを示します。 Mobile SDK のバージョン Cordova または PhoneGap のバージョン 1.2 PhoneGap 1.2 1.3 Cordova 1.8.1 1.4 Cordova 2.2 1.5 Cordova 2.3 2.0 Cordova 2.3 2.1 Cordova 2.3 2.2 Cordova 2.3 ユーザエージェントを使用した Mobile SDK のバージョンの検出 Mobile SDK のバージョンは、ユーザエージェントで確認できます。ユーザエージェントは、 SalesforceMobileSDK/<version> で開始します。ユーザエージェントを取得したら、返された文字列を解析 して Mobile SDK のバージョンを検出できます。 115 ハイブリッド開発の概要 ハイブリッドアプリケーションでのセッション管理 ユーザエージェントは、サーバで次の 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) このメソッドは、次の情報を提供する連想配列を返します。 メンバー名 説明 sdkVersion コンテナの作成に使用される Salesforce Mobile SDK の バージョン (「1.4」など)。 appName ハイブリッドアプリケーションの名前。 appVersion ハイブリッドアプリケーションのバージョン。 forcePluginsAvailable コンテナにインストールされた Salesforce プラグインの 名前を含む配列 (「com.salesforce.oauth」、 「com.salesforce.smartstore」など)。 次のコードは、sdkinfo プラグインに保存された情報を取得して、アラートボックスに表示します。 var sdkinfo = cordova.require("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 つのサイズですべてに対応)」というアプローチは制限が厳しすぎることがわ 116 ハイブリッド開発の概要 ハイブリッドアプリケーションでのセッション管理 かっています。たとえば、モバイルアプリケーションで JavaScript remoting in Visualforce で使用していると、セッ ションが期限切れになった場合に Salesforce Cookie が失われることがあります。この Cookie は、ユーザが手動で 再度ログインした場合にのみ取得されます。 Mobile SDK 1.4 では、事前定義されたプロアクティブなセッション管理から、より柔軟でリアクティブなセッ ション管理へのハイブリッドアプリケーションの移行を開始しました。ハイブリッドコンテナでセッションを自 動的に管理するのではなく、セッションイベントに応答することによって開発者が管理に関与できるようになり ました。この変更により、開発者は、Salesforce Touch プラットフォームでセッション管理をさらに細かく制御で きます。 リアクティブ管理に切り替えるには、アプリケーションのアーキテクチャに応じてセッション管理の設定を調整 します。次の表には、一般的なアーキテクチャの動作と推奨されるアプローチがまとめられています。 アプリケーションアーキテ SDK 1.3 以前のプロアク クチャ ティブな動作 SDK 1.4 でのリアクティブ コードのアップグレード手 な動作 順 REST API バックグラウンドセッショ JavaScript からの更新 ンの更新 JavaScript Remoting in Visualforce アプリケーションの再起動 JavaScript からのセッション タイムアウトをキャッチ と CSRF トークンの更新 し、ページの再読み込みま たは新しい iFrame の読み 込みを行います。 jQuery Mobile アプリケーションの再起動 ページの再読み込み forcetk.mobilesdk.js は変更さ れません。他のフレーム ワークについては、更新 コードを追加します。 タイムアウトをキャッチ し、ページの再読み込みを 行います。 次のセクションでは、各アーキテクチャの詳しいコーディング手順を示します。 REST API (Apex2REST を含む) REST API を活用するハイブリッドアプリケーションを作成またはアップグレードする場合、REST コールが行 われた時点で期限切れのセッションを検出し、新しいアクセストークンを要求します。アプリケーションの作成 者は、このフレームワークに基づき、forcetk.mobilesdk.js などの API ラップ用ライブラリを活用してセッション の保有期間を管理してください。 ContactExplorer サンプルアプリケーションにある index.html の次のコードは、推奨される技法を示していま す。アプリケーションを初めて読み込む場合、更新関数のハンドル (この場合は salesforceSessionRefreshed) を渡して Salesforce OAuth プラグインで getAuthCredentials() をコールします。OAuth プラグイン関数は、 更新関数をコールし、セッションおよび更新トークンを渡します。返された値を使用して、forcetk.mobilesdk を 初期化します。 • onDeviceReady() 関数から: cordova.require("salesforce/plugin/oauth").getAuthCredentials(salesforceSessionRefreshed, getAuthCredentialsError); 117 ハイブリッド開発の概要 • ハイブリッドアプリケーションでのセッション管理 salesforceSessionRefreshed() 関数: function salesforceSessionRefreshed(credsData) { forcetkClient = new forcetk.Client(credsData.clientId, credsData.loginUrl); forcetkClient.setSessionToken(credsData.accessToken, apiVersion, credsData.instanceUrl); forcetkClient.setRefreshToken(credsData.refreshToken); forcetkClient.setUserAgentString(credsData.userAgent); } 完全なコードについては、ContactExplorer サンプルアプリケーション (SalesforceMobileSDK-Android\hybrid\SampleApps\ContactExplorer) を参照してください。 JavaScript Remoting in Visualforce JavaScript 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 page window.location.reload(); } else { // Everything is OK. You can go ahead and use the result. }, {escape: true} ); この例では、hasSessionExpired() を次のように定義します。 function hasSessionExpired(event) { return (event.type == "exception" && event.message.indexOf("Logged in?") != -1); } 上級開発者: ページ全体を再読み込みしても、最適なユーザ操作性が提供されない場合があります。ページ全体 の再読み込みを回避するには、次の操作が必要です。 1. アクセストークンを更新します。 2. Visualforce ドメインの Cookie を更新します。 3. 最後に、CSRF トークンを更新します。 hasSessionExpired() で、次のようなページの完全な再読み込みは行いません。 window.location.reload(); 代わりに、次のようにします。 // Refresh oauth token cordova.require("salesforce/plugin/oauth").authenticate( function(creds) { // Reload hidden iframe that points to a blank page to // to refresh Visualforce domain cookies 118 ハイブリッド開発の概要 例: 適切な JavaScript ライブラリの提供 var iframe = document.getElementById("blankIframeId"); iframe.src = src; // Refresh CSRF cookie <provider>.refresh(function() { <Retry call for a seamless user experience>; }); }, function(error) { console.log("Refresh failed"); } ); jQuery Mobile JQueryMobile では、Ajax コールを行って、ページを表示するためのデータを転送します。セッションが期限切れ になると、フレームワークにより 302 エラーがマスクされます。エラーを回復するには、次のコードを組み込ん で、ページを強制的に更新します。 $(document).on('pageloadfailed', function(e, data) { console.log('page load failed'); if (data.xhr.status == 0) { // reloading the VF page to initiate authentication window.location.reload(); } }); 例: 適切な 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 • cordova-1.8.1.js (名前を cordova.js に変更する必要があります) SalesforceOAuthPlugin.js bootconfig.js メモ: バンドルでは、Cordova JavaScript ライブラリの名前を cordova.js (PhoneGap-x.x.js ライブ ラリを使用するバージョンをパッケージ化する場合は PhoneGap.js) に変更できます。 2. 使用するバンドルを判別する Apex コントローラを作成します。コントローラコードで、ユーザエージェント 文字列を解析して、クライアントで使用しているバージョンを見つけます。 a. 組織の [設定] から、[開発] > [Apex クラス] をクリックします。 119 ハイブリッド開発の概要 例: 適切な JavaScript ライブラリの提供 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 additional if statements for other SalesforceSDK versions // for which you provide library bundles. } } 3. バンドル内のライブラリごとに Visualforce ページを作成し、そのページを使用してクライアントを目的のラ イブラリにリダイレクトします。 たとえば、SalesforceOAuthPlugin ライブラリの場合は、次のようになります。 a. 組織の [設定] から、[開発] > [ページ] をクリックします。 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> タグを指定します。 120 第8章 HTML5 開発 トピック: • • • HTML5 の開発要件 Visualforce を使用した HTML5 コ ンテンツの配信 Salesforce データへのアクセス: コ ントローラと API HTML5 により、ターゲットデバイスにソフトウェアをインストール せずに、軽量モバイルインターフェースを作成できます。どのモバイ ルデバイス、タッチデバイス、デスクトップデバイスからでも、この モバイルインターフェースにアクセスできます。 次の方法で、Force.com プラットフォームを使用する HTML5 アプリ ケーションを作成できます。 • Visualforce を使用して、HTML コンテンツを配信する。 • JavaScript Remoting を使用して、Force.com からレコードを取得する ための Apex コントローラを呼び出す。 121 HTML5 開発 HTML5 の開発要件 HTML5 の開発要件 • Force.com 組織が必要です。 • Apex および Visualforce に関する多少の知識が必要です。 メモ: このタイプの開発では、Visualforce を使用します。Database.com は使用できません。 Visualforce を使用した HTML5 コンテンツの配信 デスクトップ環境用にカスタム Web サイトを作成するには、従来より Visualforce を使用しています。ただし、 HTML5 と組み合わせると、Visualforce がモバイル Web アプリケーションで実行できる配信メカニズムになりま す。これらのアプリケーションでは、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:actionFunction と同様に、JavaScript Remoting では、Visualforce ページでホストされる JavaScript コード を使用して、Apex コントローラでメソッドを呼び出すことができます。 JavaScript Remoting には、いくつかの利点があります。 • apex:actionFunction に比べて柔軟性に富み、パフォーマンスが高い。 • Apex コントローラメソッドでパラメータと戻り値の型がサポートされ、Apex と JavaScript 間でデータ型の対 応付けが自動的に行われる。 コールバックで非同期処理モデルを使用する。 • 122 HTML5 開発 • Salesforce データへのアクセス: コントローラと API apex:actionFunction と異なり、AJAX 要求に Visualforce ページのビューステートが含まれない。この結 果、往復速度が速くなります。 ただし、apex:actionFunction に比べて、JavaScript Remoting ではより多くのコードを作成する必要がありま す。 次の例では、Visualforce ページの <script> タグに JavaScript コードを挿入しています。このコードは、Visualforce Remoting マネージャオブジェクトで invokeAction() メソッドをコールします。Apex コントローラオブジェク ト objName で getItemId() という名前の関数をコールするのに必要なメタデータを invokeAction() に渡しま す。invokeAction() は非同期で実行されるため、getItemId() から返される値を処理するコールバック関数 もコードで定義します。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 @RemoteAction global static String getItemId(String objectName) { ... } @RemoteAction アノテーションについての詳細は、 http://www.salesforce.com/us/developer/docs/apexcode/Content/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:includeScript value="{!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(); 123 /> HTML5 開発 Salesforce データへのアクセス: コントローラと API // Get an instance of the REST API client and set the session ID var 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 をオフラインで使用する場合のヒントについては、次の記事を参照してください。 • • http://blogs.developerforce.com/developer-relations/2011/06/using-html5-offline-with-forcecom.html http://blogs.developerforce.com/developer-relations/2013/03/using-javascript-with-force-com.html 124 第9章 ファイルとネットワーキング トピック: • • • • • • • アーキテクチャ ファイルのダウンロードと共有の 管理 ファイルのアップロード 暗号化とキャッシュ Android アプリケーションでのファ イルの使用 iOS ネイティブアプリケーション でのファイルの使用 ハイブリッドアプリケーションで のファイルの使用 Mobile SDK 2.1 には、ファイルとネットワーキングのための API が導 入されています。この API には、2 つのレベルのテクノロジがありま す。ファイル管理レベルでは、SDK は Chatter REST API でファイル 要求をラップする一連の便利なメソッドを提供します。REST API ラッ パーレベルでは、ネットワーキングレイヤは待機中の REST 要求をア プリケーションで制御できるようにするオブジェクトを公開します。 このような表裏一体のテクノロジを合わせることで、堅牢な機能セッ トと高度なネットワーキングパフォーマンスを SDK で実現できます。 125 ファイルとネットワーキング アーキテクチャ アーキテクチャ Mobile SDK 2.1 以降では、Android REST 要求システムは、基盤となるアーキテクチャとしてオープンソース外 部ライブラリの Google Volley を使用します。このアーキテクチャでは、Volley QueueManager オブジェクトにア クセスして要求を管理できます。実行時には、QueueManager を使用して、非同期スレッドで待機中の要求を キャンセルできます。Volley についての詳細は、https://developers.google.com/events/io/sessions/325304728 を参照 してください。 iOS では、SalesforceNetworkSDK ライブラリを使用して、ファイル管理およびネットワーキングを行います。 ファイルや他の REST 要求の REST API コールは、すべてこのライブラリを経由します。SalesforceNetworkSDK ライブラリ自体は、一般的なオープンソースライブラリである MKNetworkKit を実装します。 メモ: 古いバージョンの Mobile SDK iOS アプリケーションで RestKit ライブラリに直接アクセスした場 合、MKNetworkKit ライブラリを使用するようにそのコードを更新する必要があります。 ハイブリッド JavaScript 関数では、デバイスのオペレーティングシステム (Android または iOS) に対応する Mobile SDK のアーキテクチャを使用して、ファイル操作を実装します。これらの関数は、forcetk.mobilesdk.js で 定義されています。 ファイルのダウンロードと共有の管理 Salesforce Mobile SDK には、ファイルのダウンロード操作や共有操作のための特殊な REST 要求を構築する便利 なメソッドがあります。これらの要求を使用して、次のことを実行できます。 • ファイルのバイトストリームにアクセスする。 • ファイルのページをダウンロードする。 • ファイルのページをプレビューする。 • ファイルレコードの詳細を取得する。 • ファイル共有情報にアクセスする。 • ファイル共有を追加および削除する。 要求のページ REST 要求の「ページ」という用語は、コンテキストに応じて結果セットの特定項目または項目グループを表し ます。たとえば、特定のファイルのページをプレビューする場合、要求は表示されたページの中から指定された ページを取得します。他の大部分の要求では、ページとは結果のリストのセクションを表します。1 ページのレ コードまたはトピックの最大数は、デフォルトの 25 に設定されます。 応答には、NextPageUrl 項目が含まれます。この値が定義されている場合、結果には別のページがあります。 アプリケーションで結果のページをスクロールする場合、この項目を使用して不要な要求が送信されないように できます。また、応答状況を確認するだけで、リストの最後であるかどうかを検出することもできます。何も返 されない場合やエラーが返される場合は、これ以上表示するものがないため、別の要求を発行する必要はありま せん。 126 ファイルとネットワーキング ファイルのアップロード ファイルのアップロード ネイティブモバイルプラットフォームでは、ファイルをアップロードするためのメソッドがサポートされていま す。アップロードするローカルファイルへのパス、ファイルの名前またはタイトル、および説明を入力します。 MIME タイプがわかっている場合、そのタイプも指定できます。アップロードメソッドは、ファイルをサーバに アップロードできるプラットフォーム固有の要求オブジェクトを返します。この要求をサーバに送信すると、 バージョンが 1 に設定されたファイルがサーバで作成されます。 次に、アプリケーション種別ごとに使用するメソッドを示します。 アプリケーション Upload メソッド 種別 署名 Android ネイティ ブ FileRequests.uploadFile() public static RestRequest uploadFile( File theFile, String name, String description, String mimeType) throws UnsupportedEncodingException iOS ネイティブ - requestForUploadFile: name:description:mimeType: - (SFRestRequest *) requestForUploadFile:(NSData *)data name:(NSString *)name description:(NSString *)description mimeType:(NSString *)mimeType ハイブリッド (Android と iOS) なし なし 暗号化とキャッシュ Mobile SDK 2.1 は、ファイルの暗号化されていないバイトストリームへのアクセスを提供しますが、ファイルの キャッシュまたは保存は実装しません。アプリケーションでファイルをデバイスに保存する必要がある場合、独 自の解決策を自由に考案できます。 Android アプリケーションでのファイルの使用 FileRequests クラスは、ファイル操作を実行する RestRequest オブジェクトを作成するための静的メソッド を提供します。各メソッドは、新しい RestRequest オブジェクトを返します。次に、アプリケーションは ownedFilesList() メソッドをコールして RestRequest オブジェクトを取得します。このオブジェクトは、 RestRequest オブジェクトを使用してサーバに要求を送信する関数にパラメータとして渡されます。 performRequest(FileRequests.ownedFilesList(null, null)); 127 ファイルとネットワーキング 要求キューの管理 この例では、null を最初のパラメータ (userId) に渡します。この値で、コンテキスト (ログインしている) ユー ザの ID を使用するように ownedFilesList() メソッドに指示しています。pageNum パラメータの 2 番目の null で、結果の最初のページを取得するようにメソッドに指示します。 ネイティブ Android アプリケーションの場合、ファイル管理クラスおよびメソッドは com.salesforce.androidsdk.rest.files パッケージにあります。 関連リンク FileRequests メソッド (Android) 要求キューの管理 RestClient クラスは、内部的に Volley RequestQueue クラスのインスタンスを使用して REST API 要求を管理 します。基盤となる RequestQueue オブジェクトにアクセスするには、RestClient インスタンスで restClient.getRequestQueue() をコールします。RequestQueue オブジェクトを使用すると、待機中の要求 を直接キャンセルまたは操作できます。 例: 待機中のすべての要求のキャンセル 次のコードでは、RestClient (client) のインスタンスで getRequestQueue() をコールします。次に、 RequestQueue.cancelAll() メソッドをコールして、キューにある待機中のすべての要求をキャンセルしま す。cancelAll() メソッドは RequestFilter パラメータを受け入れるため、コードでは、Volley RequestFilter インターフェースを実装するカスタムクラス CountingFilter のオブジェクトを渡します。 CountingFilter countingFilter = new CountingFilter(); client.getRequestQueue().cancelAll(countingFilter); int count = countingFilter.getCancelCount(); ... /** * Request filter that cancels all requests and also counts the number of requests canceled * */ class CountingFilter implements RequestFilter { private int count = 0; public int getCancelCount() { return count; } @Override public boolean apply(Request<?> request) { count++; return true; } } RequestQueue.cancelAll() では、操作の続行を許可する前に RequestFilter ベースのオブジェクトで キューの各項目を調べることができます。cancelAll() は、各反復でフィルタの apply() メソッドを内部的 にコールします。apply() で true が返されると、キャンセル操作は続行されます。false が返されると、 cancelAll() はその要求をキャンセルせずにキューの次の要求に進みます。 128 ファイルとネットワーキング iOS ネイティブアプリケーションでのファイルの使用 このコード例では、CountingFilter.apply() は、コールごとに単純に内部カウンタを増分します。このサ ンプルコードでは、cancelAll() 操作の完了後に CountingFilter.getCancelCount() をコールして、キャ ンセルしたオブジェクト数をレポートします。 iOS ネイティブアプリケーションでのファイルの使用 ネイティブ iOS アプリケーションでファイルを処理するには、SFRestAPI (Files) カテゴリで定義されている 便利なメソッドを使用します。これらのメソッドは、Android ネイティブアプリケーションとハイブリッドアプ リケーションの Files API と似ています。これらは、要求を REST API の同じリストに送信しますが、異なる基 盤を使用します。 iOS プロジェクトの設定 Mobile SDK 2.1 より前に構築された Salesforce Mobile SDK アプリケーションを更新する場合、すべてのターゲッ トに SalesforceNetworkSDK ライブラリが含まれるようにプロジェクトの設定を調整する必要があります。 1. Mobile SDK 2.1 に付属する MKNetworking ライブラリをダウンロードします。 https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Distribution の圧縮ファイルからバイナリライブラリ とそれらのヘッダーを取得します。 2. プロジェクトで次のモジュールをリンクします。 • • • libMKNetworkKit-iOS.a libSalesforceNetworkSDK.a ImageIO.framework Files API では、次のフレームワークも必要になります。通常、これらはデフォルトでリンクされています。 • • • CFNetwork.framework SystemConfiguration.framework Security.framework REST 応答とマルチスレッド ネットワーキングライブラリは常に、現在 SFRestDelegate が実行されているスレッドに REST 応答を送りま す。この設計では、代理メソッドでどのようにサーバ応答を処理しても、目的の用途に対応できます。応答を受 信したら、返されたデータを使用して任意の操作を実行できます。たとえば、キャッシュしたり、データベース に保存したり、すぐに UI コントロールに一括送信したりできます。ただし、応答を直接 UI に送信する場合代理 メソッドでそのメッセージをメインスレッドに送る必要があります。 関連リンク SFRestAPI (Files) カテゴリ — 要求メソッド (iOS) 要求の管理 MKNetworkKit (iOS Mobile SDK の基盤となるネットワーキングアーキテクチャ) は、MKNetworkEngine と MKNetworkOperation の 2 つのキーオブジェクトを使用します。次に、Salesforce Network SDK for iOS は、対応 する MKNetworkKit オブジェクトをラップする SFNetworkEngine と SFNetworkOperation の 2 つの主オブジェ 129 ファイルとネットワーキング ハイブリッドアプリケーションでのファイルの使用 クトを定義します。SFRestRequest は、内部的に SFNetworkOperation オブジェクトを使用して、各サーバ コールを実行します。 要求のために SFNetworkOperation オブジェクトにアクセスする方法は 2 つあります。 • 次のメソッドは SFNetworkOperation* を返します。 ◊ [SFRestRequest send:] ◊ [SFRestAPI send:delegate:] • SFRestRequest オブジェクトには、種別が SFNetworkOperation* の networkOperation オブジェクトが 含まれます。 待機中の REST 要求をキャンセルする方法も 2 つあります。 • SFRestRequest は、要求をキャンセルする新しいメソッドを提供します。 - (void) cancel; • SFRestAPI には、現在実行されているすべての要求をキャンセルするメソッドがあります。 - (void)cancelAllRequests; 要求をキャンセルする方法の例 すべての要求をキャンセルする [[SFRestAPI sharedInstance] cancelAllRequests]; 1 つの要求をキャンセルする SFRestRequest *request = [[SFRestAPI sharedInstance] requestForOwnedFilesList:nil page: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 ライブラリにあります。 ハイブリッド関数を使用する場合、サーバ応答を受信して処理するコールバック関数を渡します。また、エラー を処理する関数も渡します。 130 ファイルとネットワーキング ハイブリッドアプリケーションでのファイルの使用 コードを簡素化するために、SmartSync.js および forcetk.mobilesdk.js ライブラリを利用して、HTML ア プリケーションを構築できます。HybridFileExplorer サンプルアプリケーションは、この方法を示します。 メモ: Mobile SDK では、ハイブリッドアプリケーションでのファイルのアップロードをサポートしてい ません。 関連リンク ハイブリッドアプリケーションの Files メソッド 131 第 10 章 SmartSync を使用した Salesforce オブジェクトへのアクセス トピック: • • • • • • • • Backbone テクノロジについて モデルとモデルコレクション JavaScript での SmartSync Data Framework の使用 オフラインキャッシュ 競合検出 カスタム API エンドポイントへの アクセス チュートリアル: SmartSync アプリ ケーションの作成 SmartSync サンプルアプリケーショ ン SmartSync Data Framework は、Salesforce オブジェクトを JavaScript オブ ジェクトとして表す Mobile SDK ライブラリです。ハイブリッドアプ リケーションで SmartSync を使用すると、Salesforce オブジェクトのモ デルを作成でき、そのモデルのデータを変更するだけで基盤となるレ コードを操作できます。SOQL または SOSL クエリを実行すると、 JSON 文字列としてではなくモデルコレクションで結果レコードが取 得されます。 基盤となる SmartSync テクノロジは、backbone.js のオープンソース JavaScript ライブラリです。Backbone.js は、データをモデル化する 拡張可能なメカニズムを定義します。SmartSync Data Framework の背 後にある基盤テクノロジを理解するには、backbonejs.org の例やドキュ メントを参照してください。 次の 3 つのハイブリッドサンプルアプリケーションで SmartSync を使 用できます。 • • • Account Editor (AccountEditor.html) User Search (UserSearch.html) User and Group Search (UserAndGroupSearch.html) これらのサンプルアプリケーション は、./hybrid/SampleApps/AccountEditor/assets/www フォルダ にあります。 132 SmartSync を使用した Salesforce オブジェクトへのアク セス Backbone テクノロジについて 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」を検索すれば、多数のチュートリアルやビデオを見つけることもできま す。 モデルとモデルコレクション SmartSync Data Framework は、次の 2 つの種別のオブジェクトで構成されています。 • モデル • モデルコレクション これらのオブジェクトの定義は、backbone.js (一般的なサードパーティの JavaScript フレームワーク) で定義さ れているクラスを拡張します。背景情報は、http://backbonetutorials.com を参照してください。 モデル クライアントのモデルはサーバレコードを表します。SmartSync では、モデルオブジェクトは Force.SObject (Backbone.Model クラスのサブクラス) のインスタンスです。SObject は、Salesforce API および SmartStore (必 要に応じて) と連動するように Model を拡張します。 SObject モデルオブジェクトで次の CRUD 操作を実行できます。 • • • • • Create Destroy Fetch Save Get/set attributes また、モデルオブジェクトは監視可能です。ビューとコントローラはオブジェクトの変更時に通知を受信できま す。 プロパティ Force.SObject は、次のプロパティを Backbone.Model に追加します。 133 SmartSync を使用した Salesforce オブジェクトへのアク セス モデル sobjectType 必須。このモデルが表す Salesforce オブジェクトの名前。この値は、標準オブジェクトまたはカスタムオブ ジェクトのいずれかを参照できます。 fieldlist 必須。取得、保存、破棄する項目の名前。 cacheMode オフラインの動作。 mergeMode 競合処理の動作。 cache 更新可能なレコードのオフラインストレージの場合に使用します。SmartSync Data Framework には、 Force.StoreCache (SmartStore によってサポートされるキャッシュ実装) が組み込まれています。 cacheForOriginals 競合検出に対応できるように、サーバから取得したレコードの元のコピーを格納します。 例 モデルプロパティの値は、次のような複数の方法で割り当てることができます。 • Force.SObject インスタンスのプロパティとして割り当てる。 • Force.SObject サブクラスのメソッドとして割り当てる。これらのメソッドでは、目的の CRUD アクショ • ン (「create」、「create」、「update」、「delete」) を指定するパラメータを使用します。 fetch()、save()、destroy() 関数コールのパラメータで割り当てる。 たとえば、次のコードスニペットはどれも同じ内容になります。 // As properties on a Force.SObject instance acc = new Force.SObject({Id:"<some_id>"}); acc.sobjectType = "account"; acc.fieldlist = ["Id", "Name"]; acc.fetch(); // As methods on a Force.SObject sub-class Account = 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"]); 134 SmartSync を使用した Salesforce オブジェクトへのアク セス モデルコレクション モデルコレクション 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 によってサポートされるキャッシュ実装) が組み込まれています。 cacheForOriginals 競合検出に対応できるように、サーバから取得したレコードの元のコピーを格納します。 例 モデルコレクションプロパティの値は、次のような複数の方法で割り当てることができます。 • Force.SObject インスタンスのプロパティとして割り当てる • Force.SObject サブクラスのメソッドとして割り当てる • fetch()、save()、destroy() 関数コールのオプションパラメータで割り当てる たとえば、次のコードスニペットはどれも同じ内容になります。 // As properties on a Force.SObject instance list = new Force.SObjectCollection({config:<valid_config>}); list.fetch(); // As methods on a Force.SObject sub-class MyCollection = 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}); 135 SmartSync を使用した Salesforce オブジェクトへのアク セス JavaScript での SmartSync Data Framework の使用 JavaScript での SmartSync Data Framework の使用 SmartSync をハイブリッドアプリケーションで使用するには、次のファイルが必要になります。 • jquery-x.x.x.min.js (external/shared/jquery/ のファイルのバージョンを使用) • underscore-x.x.x.min.js (external/shared/backbone/ のファイルのバージョンを使用) • backbone-x.x.x.min.js (external/shared/backbone/ のファイルのバージョンを使用) • • • • cordova.js cordova.force.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 型の プロパティか、文字列を返す関数のいずれかになります。 モデルコレクションの実装 このサンプルアプリケーションのモデルコレクションは、Force.SObjectCollection を拡張します。 // The AccountCollection Model app.models.AccountCollection = Force.SObjectCollection.extend({ model: app.models.Account, fieldlist: ["Id", "Name", "Industry", "Phone"], setCriteria: function(key) { this.key = key; }, config: function() { 136 SmartSync を使用した Salesforce オブジェクトへのアク セス オフラインキャッシュ // Offline: do a cache query if (app.offlineTracker.get("offlineStatus") == "offline") { return {type:"cache", cacheQuery:{queryType:"like", indexPath:"Name", likeKey: this.key+"%", order:"ascending"}}; } // Online else { // First time: do a MRU query if (this.key == null) { return {type:"mru", sobjectType:"Account", fieldlist: this.fieldlist}; } // Other times: do a SOQL query else { 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 は、キャッシュの操作を完全に制御できるメカニズム (設定可能) を提供します。 デフォルトキャッシュおよびカスタムキャッシュの実装 デフォルトキャッシュの場合、SmartSync ライブラリは StoreCache (SmartStore を使用するキャッシュ実装) を定 義します。StoreCache と SmartStore はどちらも SmartSync アプリケーションのコンポーネント (省略可能) です。 アプリケーションが Mobile SDK コンテナではなくブラウザで実行されている場合や、SmartStore を使用しない 場合、代替キャッシュ実装を提供する必要があります。SmartSync では、次の操作をサポートするためにキャッ シュオブジェクトが必要になります。 • • • • • retrieve save save all remove find 137 SmartSync を使用した Salesforce オブジェクトへのアク セス オフラインキャッシュ SmartSync のキャッシュワークフロー SmartSync モデルは、アプリケーションの代わりにキャッシュおよび Salesforce サーバとのすべてのやり取りを実 行します。アプリケーションは、モデルオブジェクトの属性を取得および設定します。モデルは、保存操作時に これらの属性設定を使用して、変更をキャッシュまたはサーバに書き込むかどうかを判断したり、新しいデータ と既存のデータのマージ方法を決定したりします。基本データまたはモデル自体に何らかの変更があると、モデ ルはイベント通知を送信します。同様に、取得を要求すると、モデルはモデルコレクションでデータを取得して アプリケーションに提供します。 SmartSync は、CRUD 操作時にキャッシュのデータを透過的に更新します。フラグ (省略可能) を介して透過レベ ルを制御できます。キャッシュされたオブジェクトは、ローカルで作成、更新、削除されたかどうかを示す 「dirty」属性を保持します。 キャッシュモデル キャッシュを使用する場合、各 CRUD 操作のモデルを指定できます。サポートされるモードは次のとおりです。 モード 定数 説明 "cache-only" Force.CACHE_MODE.CACHE_ONLY キャッシュから読み取る か、キャッシュに書き込 みます。サーバの操作は 実行しません。 "server-only" Force.CACHE_MODE.SERVER_ONLY サーバから読み取るか、 サーバに書き込みます。 キャッシュの操作は実行 しません。 138 SmartSync を使用した Salesforce オブジェクトへのアク セス オフラインキャッシュの実装 モード 定数 説明 "cache-first" Force.CACHE_MODE.CACHE_FIRST 取得操作の場合のみ。 キャッシュからレコード を取得します。キャッ シュにレコードが含まれ ていない場合、サーバか ら取得してキャッシュを 更新します。 "server-first" (デ フォルト) Force.CACHE_MODE.SERVER_FIRST サーバの操作を実行し、 キャッシュを更新しま す。 直接キャッシュをクエリするには、キャッシュクエリを使用します。SmartStore は、クエリ API、独自のクエリ 言語、Smart SQL を提供します。「スープからのデータの取得」を参照してください。 オフラインキャッシュの実装 SmartSync でオフラインキャッシュをサポートするには、次のようないくつかのタスクを実装する必要がありま す。 • app.models.Account の例で示すようにオフライン状況を追跡して、CRUD 操作の適切なキャッシュコント ロールフラグを指定する。 • ローカルで編集されたレコードを収集し、デバイスがオンラインに戻ったときにその変更をサーバに保存す る。次の例では、SmartStoreキャッシュクエリを使用して、ローカルで変更されたレコードを取得し、SyncPage 関数をコールして、HTML でその結果を表示しています。 sync: function() { var that = this; 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; }, ... }); 139 SmartSync を使用した Salesforce オブジェクトへのアク セス オフラインキャッシュのための StoreCache の使用 オフラインキャッシュのための 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 を検索し ます。 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 を返し ます。 140 SmartSync を使用した Salesforce オブジェクトへのアク セス オフラインキャッシュのための StoreCache の使用 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 です。 saveAll(records [, noMerge]) records が、保存されるレコードの配列である点を除き、save() と同じです。保存されるレコードに解決 する jQuery promise を返します。 records レコードの配列。配列の各項目は、save() 関数に示されるように書式設定されます。 noMerge (省略可能) 渡されたレコードが、一致するサーバレコードとマージされるかどうかを示す boolean 値。 デフォルトは false です。 remove(key) 指定されたキーを持つレコードが SmartStore から削除されたときに解決する jQuery promise を返します。 141 SmartSync を使用した Salesforce オブジェクトへのアク セス オフラインキャッシュのための StoreCache の使用 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>} {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 soup cache.init() .then(function() { // saving a record to the cache return cache.save({Id:"007", Name:"JamesBond", Mission:"TopSecret"}); 142 SmartSync を使用した Salesforce オブジェクトへのアク セス 競合検出 }) .then(function(savedRecord) { // retrieving a record from the cache return cache.retrieve("007"); }) .then(function(retrievedRecord) { // searching for records in the cache return cache.find({queryType:"like", indexPath:"Mission", likeKey:"Top%", order:"ascending", pageSize:1}); }) .then(function(result) { // removing a record from the cache return cache.remove("007"); }); 次の例では、saveAll() 関数の使用方法と find() 関数の結果を示します。 // initialization var cache = new Force.StoreCache("agents", [ {path:"Name", type:"string"}, {path:"Mission", type:"string"} ]); cache.init() .then(function() { // saving some records return cache.saveAll([{Id:"007", Name:"JamesBond"},{Id:"008", Name:"Agent008"}, {Id:"009", Name:"JamesOther"}]); }) .then(function() { // doing an exact query return cache.find({queryType:"exact", indexPath:"Name", matchKey:"Agent008", order:"ascending", pageSize:1}); }) .then(function(result) { alert("Agent mission is:" + result.records[0]["Mission"]; }); 競合検出 モデルオブジェクトは、オブジェクトをサーバに保存するときに不要なデータ損失を回避する競合検出 (省略可 能) をサポートしています。競合検出は、デバイスがオフライン状態から復帰しているかどうかに関係なく、任 意の保存操作と共に使用できます。 競合検出をサポートするには、サーバから取得した元の値を格納するセカンダリキャッシュを指定します。 SmartSync は、後で参照できるようにこのキャッシュを保持します。保存または削除する場合、マージモードを 指定します。次の表に、サポートされるモードの概要を示します。モードの説明を理解するには、「theirs」を現 在のサーバレコード、「yours」を現在のローカルレコード、「base」をサーバから最初に取得したレコードとし て考えます。 モード 定数 説明 overwrite Force.MERGE_MODE.OVERWRITE 「theirs」または「base」 と比較することなく 「yours」をサーバに書き 込みます。これは、競合 検出を使用しない場合と 同じです。 143 SmartSync を使用した Salesforce オブジェクトへのアク セス 競合検出 モード 定数 説明 merge-accept-yours Force.MERGE_MODE.MERGE_ACCEPT_YOURS 「theirs」と「yours」を マージします。同じ項目 がローカルとリモートの 両方で変更された場合、 ローカルの値が保持され ます。 merge-fail-if-conflict Force.MERGE_MODE.MERGE_FAIL_IF_CONFLICT 「theirs」と「yours」を マージします。同じ項目 がローカルとリモートの 両方で変更された場合、 この操作は失敗します。 merge-fail-if-changed Force.MERGE_MODE.MERGE_FAIL_IF_CHANGED 「theirs」と「yours」を マージします。何らかの 項目がリモートで変更さ れた場合、この操作は失 敗します。 保存または削除操作が失敗した場合、次の項目を含むレポートオブジェクトを取得します。 項目名 次の文字列を含む base 最初に取得した属性 theirs 最新のサーバ属性 yours ローカルで変更された属性 remoteChanges base と theirs 間で変更された項目のリスト localChanges base と yours 間で変更された項目のリスト conflictingChanges 異なる値を使用して theirs と yours の両方で変更された 項目のリスト ダイアグラムは、マージモードの仕組みを明確にするのに役立ちます。 MERGE_MODE.OVERWRITE MERGE_MODE.OVERWRITE ダイアグラムでは、クライアントは A と B を変更し、サーバは B と C を変更していま す。B への変更は競合していますが、A と C への変更は競合していません。ただし、保存操作では、すべてのク ライアントの値が無差別にサーバに書き込まれるため、サーバの変更が上書きされます。 144 SmartSync を使用した Salesforce オブジェクトへのアク セス 競合検出 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 を変更し ています。これらの競合する変更が原因で保存操作が失敗します。 MERGE_FAIL_IF_CONFLICT (成功) 2 番目の MERGE_MODE.MERGE_FAIL_IF_CONFLICT ダイアグラムでは、クライアントは A を変更し、サーバは B を変更しています。これらの変更は競合しないため、保存操作は成功します。 145 SmartSync を使用した Salesforce オブジェクトへのアク セス ミニチュートリアル: 競合検出 ミニチュートリアル: 競合検出 次のミニチュートリアルでは、さまざまな状況下でマージモードが保存操作にどのような影響を与えるかについ て説明します。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"); 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」、業種が「サービス」に変更されるとします。 146 SmartSync を使用した Salesforce オブジェクトへのアク セス カスタム API エンドポイントへのアクセス 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"]} }); サーバとキャッシュの両方で名前項目が変更されて競合が発生しているため、エラーコールバックがコール されます。 11. "merge-accept-yours" マージモードを使用して再度保存します。マージモードでは、どちらの名前の値を受け 入れるかが save() 関数に通知されているため、このマージは成功します。また、業種を変更していないた め、この項目は競合しません。 account.save(null, {mergeMode: "merge-accept-yours"}); 名前は「Acme4」(yours) で、業種は「サービス」(theirs) です。どちらもキャッシュとサーバにあります。 カスタム API エンドポイントへのアクセス Mobile SDK 2.1 では、すべての REST API を操作できるように SmartSync の範囲が拡張されています。以前は、 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 が以前に行っていたすべてのことを実行します。 147 SmartSync を使用した Salesforce オブジェクトへのアク セス Force.RemoteObjectCollection クラス 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); } }) 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 値を返す関数 148 SmartSync を使用した Salesforce オブジェクトへのアク セス Force.RemoteObjectCollection クラス • 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 = 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; }); } }; }); 149 SmartSync を使用した Salesforce オブジェクトへのアク セス Apex REST リソースの使用 } }); Apex REST リソースの使用 Apex REST リソースをサポートするために、Mobile SDK には、Force.ApexRestObject と Force.ApexRestObjectCollection の 2 つのクラスが用意されています。これらのクラスは、それぞれ Force.RemoteObject と Force.RemoteObjectCollection をサブクラス化し、Apex REST を使用して作成し た REST API と通信できます。 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<String, String> doGet() { String id = getIdFromURI(); Account acc = [select Id, Name from Account where Id = :id]; return new Map<String, String>{ 'accountId'=>acc.Id, 'accountName'=>acc.Name}; } @HttpPost global static Map<String, String> doPost(String accountName) { Account acc = new Account(Name=accountName); insert acc; return new Map<String, String>{ 'accountId'=>acc.Id, 'accountName'=>acc.Name}; } @HttpPatch global static Map<String, String> doPatch(String accountName) { String id = getIdFromURI(); Account acc = [select Id from Account where Id = :id]; acc.Name = accountName; update acc; return new Map<String, String>{ 'accountId'=>acc.Id, 'accountName'=>acc.Name}; } 150 SmartSync を使用した Salesforce オブジェクトへのアク セス Apex REST リソースの使用 @HttpDelete global static void doDelete() { String id = getIdFromURI(); Account acc = [select Id from Account where Id = :id]; delete acc; RestContext.response.statusCode = 204; } } 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:"<valid id>"}) 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> } 151 SmartSync を使用した Salesforce オブジェクトへのアク セス Apex REST リソースの使用 例 「simple account」という名前の Apex REST リソースを作成したとします。これは、指定された名前と一致す る「simple account」を返します。 @RestResource(urlMapping='/simpleAccounts/*') global with sharing class SimpleAccountsResource { @HttpGet global static SimpleAccountsList doGet() { String namePattern = RestContext.request.params.get('namePattern'); List<SimpleAccount> records = new List<SimpleAccount>(); for (SObject sobj : Database.query( 'select Id, Name from Account where 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(); 152 SmartSync を使用した Salesforce オブジェクトへのアク セス 外部オブジェクトの使用 (ベータ) メモ: 通常、SmartSync のコール (fetch() など) では、正常なコールバック関数およびエラーコール バック関数を定義するオプションパラメータを渡します。次に例を示します。 acc.fetch({success:function(){alert("fetched " + accs.models.length + " simple accounts");}}); 外部オブジェクトの使用 (ベータ) メモ: プレスリリースや公式声明で参照されている未リリースのサービスまたは機能は、現在利用でき ず、提供が遅れたり中止されたりする可能性があります。サービスのご購入をご検討中のお客様は、現 在利用可能な機能に基づいて購入をご決定ください。 外部オブジェクトについて (ベータ) Salesforce の外部に保存されているデータと組織内のデータを併用することが必要になる場合があります。たとえ ば、より簡単に在庫を一致させられるように、外部データベースに存在する倉庫情報にアクセスする必要が生じ る場合があります。Salesforce では、組織内から外部データソースに接続して必要なデータにアクセスし、データ の外部オブジェクトを作成して特定のユーザがタブからアクセスできるようにすることができます。外部オブ ジェクトの定義についての詳細は、http://help.salesforce.com/apex/HTViewHelpDoc?id=external_object_manage.htm を参照してください。 メモ: Salesforce API では、外部オブジェクトの参照しかできません。CRUD 操作はサポートされていま せん。 Mobile SDK アプリケーションでの外部オブジェクトへのアクセス (ベータ) Mobile SDK で外部オブジェクトにアクセスするには、SmartSync.js を使用します。Force.SObject 自体また は Force.SObject のサブクラスのいずれかのインスタンスを作成します。このインスタンスを次のように設定 します。 • idAttribute に「ExternalId」を設定する。 • キャッシュを使用する場合は、idField を「ExternalId」に設定する。 例: SmartSync を使用して外部オブジェクトを取得する 次の JavaScript の例では、Force.SObject を拡張して、項目名が CategoryName__c の Categories__x という 外部オブジェクトにアクセスします。 1. StoreCache を使用してキャッシュを設定します。 var cache = new Force.StoreCache("categories", ["CategoryName__c"], "ExternalId"); cache.init(); 153 SmartSync を使用した Salesforce オブジェクトへのアク セス チュートリアル: SmartSync アプリケーションの作成 2. クライアントの Categories__x オブジェクトを表す Force.SObject サブクラスを作成します。idAttribute を「ExternalId」に設定して cache を渡し、キャッシュを有効にします。 var Category = Force.SObject.extend({ sobjectType:"Categories__x", idAttribute:"ExternalId", fieldlist:["CategoryName__c"], cache:cache}); 3. 外部 ID が「1」の外部オブジェクトを取得できる Category のインスタンスを作成し、そのオブジェクトを 取得します。 var cat = new Category({"ExternalId": "1"}); cat.fetch(); 4. キャッシュから取得されたオブジェクトを取得します。 var cat1 = cache.retrieve("1"); 例: SmartSync を使用して外部オブジェクトのコレクションを取得する クライアントの Category オブジェクトのコレクションを表す Force.SObjectCollections オブジェクトを使用 することもできます。 1. Force.SObjectCollection のサブクラスを作成します。 var Categories = Force.SObjectCollection.extend({model:Category, cache:cache}); 2. SOQL クエリを実行して Categories__x オブジェクトを取得します。 var categories = new Categories(); categories.fetch({config:{ type:"soql", query:"SELECT ExternalId, CategoryName__c FROM Categories__x"} }); 3. キャッシュ内のコレクションから取得される、外部 ID が「2」のオブジェクトを取得します。 var cat2 = cache.retrieve("2"); チュートリアル: SmartSync アプリケーションの作成 このチュートリアルでは、SmartSync Data Framework を使用するローカルハイブリッドアプリケーションの作成 方法について説明します。Mobile SDK 2.0 に付属するUser Search のサンプルアプリケーションを再作成します。 User Search では、Salesforce 組織のユーザレコードを検索し、ユーザレコードに関する基本情報の詳細を確認で きます。 このサンプルでは、次の Web テクノロジを使用しています。 154 SmartSync を使用した Salesforce オブジェクトへのアク セス • • • • プロジェクトの設定 Backbone.js Ratchet HTML5 JavaScript プロジェクトの設定 まず、NPM インストーラを使用して Salesforce Mobile SDK をインストールしていることを確認します。iOS の 手順は、「iOS のインストール」を参照してください。Android の手順は、「Android のインストール」を参照し てください。 また、http://maker.github.io/ratchet/ から ratchet.css ファイルをダウンロードします。 1. Mobile SDK をインストールしたら、プラットフォームのローカルハイブリッドプロジェクトを作成します。 a. iOS の場合: コマンドターミナルで、次のコマンドを入力します。 forceios create --apptype=hybrid_local --appname=UserSearch --companyid=com.acme.UserSearch --organization=Acme --outputdir=. forceios スクリプトによって、./UserSearch/UserSearch.xcode.proj にプロジェクトが作成されます。 b. Android の場合: コマンドターミナルまたは Windows コマンドプロンプトで、次のコマンドを入力します。 forcedroid create -—apptype="hybrid_local" --appname="UserSearch" --targetdir=. --packagename="com.acme.usersearch" forcedroid スクリプトによって ./UserSearch にプロジェクトが作成されます。 2. 画面の指示に従って、Eclipse (Android の場合) または Xcode (iOS の場合) で新しいプロジェクトを開きます。 3. www フォルダを開きます。 4. プロジェクトから inline.js ファイルを削除します。 5. 新しいフォルダを作成します。css という名前を付けます。 6. ratchet.css ファイルを新しい css フォルダにコピーします。 7. www フォルダで、コードエディタを使用して index.html を開き、そのすべてのコンテンツを削除します。 アプリケーションの HTML ファイルの編集 アプリケーションの基本構造を作成するには、参照、リンク、コードインフラストラクチャを格納する空の HTML ページを定義します。 1. Xcode で、index.html を編集して次の基本構造を追加します。 <!DOCTYPE html> <html> <head> </head> <body> </body> </html> 155 SmartSync を使用した Salesforce オブジェクトへのアク セス アプリケーションの HTML ファイルの編集 2. <head> 要素で、次の操作を行います。 a. Web ページではなくアプリケーションのようなページにするために拡大縮小を無効にします。 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" /> b. コンテンツタイプを設定します。 <meta http-equiv="Content-type" content="text/html; charset=utf-8"> c. モバイル用の外観になるようにリンクを ratchet.css ファイルに追加します。 <link rel="stylesheet" href="css/ratchet.css"/> d. 必要な JavaScript ファイルを含めます。 <script <script <script <script <script <script <script src="jquery/jquery-2.0.0.min.js"></script> src="backbone/underscore-1.4.4.min.js"></script> src="backbone/backbone-1.0.0.min.js"></script> src="cordova-2.3.0.js"></script> src="forcetk.mobilesdk.js"></script> src="cordova.force.js"></script> src="SmartSync.js"></script> 3. コンテンツを本文に追加します。<body> ブロックで、div タグを追加して、アプリケーション UI を格納し ます。 <body> <div id="content"></div> 名前空間でオブジェクトとクラスを保持することをお勧めします。このサンプルでは、app 名前空間を使用 して、モデルとビューを格納しています。 4. <script> タグで、アプリケーション名前空間を作成します。この名前空間を app と呼びます。 <script> var app = { models: {}, views: {} } この手順の残りの部分で、引き続きコードを <script> ブロックに追加していきます。 5. jQuery を待機するイベントリスナーおよびハンドラを追加し、Cordova をコールして認証フローを開始しま す。また、コールバック関数 appStart を指定し、ユーザのログイン情報を処理します。 jQuery(document).ready(function() { document.addEventListener("deviceready", onDeviceReady,false); }); function onDeviceReady() { cordova.require("salesforce/plugin/oauth"). 156 SmartSync を使用した Salesforce オブジェクトへのアク セス アプリケーションの HTML ファイルの編集 getAuthCredentials(appStart); } アプリケーションの初期化と認証が完了したら、Salesforce OAuth プラグインは appStart() をコールして ユーザのログイン情報を渡します。appStart() 関数は、SmartSync を初期化する Force.init() をコールし てログイン情報を SmartSync に渡します。また、appStart() 関数は、アプリケーションの Backbone Router オブジェクトを作成します。 6. <script> ブロックの最後に appStart() 関数定義を追加します。 function appStart(creds) { Force.init(creds, null, null, cordova.require("salesforce/plugin/oauth").forcetkRefresh); app.router = new app.Router(); Backbone.history.start(); } 次に、この時点の完全なアプリケーションを示します。 <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0; user-scalable=no" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <link rel="stylesheet" href="css/ratchet.css"/> <script src="jquery/jquery-2.0.0.min.js"></script> <script src="backbone/underscore-1.4.4.min.js"></script> <script src="backbone/backbone-1.0.0.min.js"></script> <script src="cordova-2.3.0.js"></script> <script src="forcetk.mobilesdk.js"></script> <script src="cordova.force.js"></script> <script src="SmartSync.js"></script> </head> <body> <div id="content"></div> <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> <script id="user-list-item" type="text/template"> <img src="<%= SmallPhotoUrl %>" class="small-img" /> <div class="details-short"> <b><%= FirstName %> <%= LastName %></b><br/> Title<%= Title %> </div> </script> <script> var app = { 157 SmartSync を使用した Salesforce オブジェクトへのアク セス SmartSync モデルおよびコレクションの作成 models: {}, views: {} }; jQuery(document).ready(function() { document.addEventListener("deviceready", onDeviceReady,false); }); function onDeviceReady() { cordova.require("salesforce/plugin/oauth"). getAuthCredentials(appStart); } function appStart(creds) { console.log(JSON.stringify(creds)); Force.init(creds, null, null, cordova.require("salesforce/plugin/oauth").forcetkRefresh); app.router = new app.Router(); Backbone.history.start(); } </script> </body> </html> SmartSync モデルおよびコレクションの作成 HTML インフラストラクチャを設定したので、次の 2 つの主オブジェクトを拡張して SmartSync を使用します。 • • Force.SObject Force.SObjectCollection これらのオブジェクトは、Backbone.Model.extend() 関数をサポートできるように Backbone.Model を拡張し ます。この関数を使用してオブジェクトを拡張するには、カスタムプロパティおよびカスタム機能を含む JavaScript オブジェクトに渡します。 1. <body> タグで、Salesforce User sObject のモデルオブジェクトを作成します。Force.SObject を拡張して、対 象とする sObject タイプおよび項目を指定します。 app.models.User = Force.SObject.extend({ sobjectType: "User", fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl", "Title", "Email", "MobilePhone","City"] }) 158 SmartSync を使用した Salesforce オブジェクトへのアク セス テンプレートの作成 2. User オブジェクトの設定直後に、User Search 結果を保持するコレクションを作成します。 Force.SObjectCollection を拡張して、コレクションの項目のモデルとして新しいモデル (app.models.User) を指定します。 app.models.UserCollection = Force.SObjectCollection.extend({ model: app.models.User }); 次に、完全なモデルコードを示します。 // Models app.models.User = Force.SObject.extend({ sobjectType: "User", fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl", "Title", "Email", "MobilePhone","City"] }); app.models.UserCollection = Force.SObjectCollection.extend({ model: app.models.User }); テンプレートの作成 テンプレートを使用すると、別の HTML ページ内に HTML レイアウトを設定できます。タイプが "text/template" の <script> タグを使用して、HTML ページにインラインテンプレートを定義できます。JavaScript コードでは、 実行時に新しい HTML ページをインスタンス化する場合、テンプレートをページの設計として使用できます。 検索ページテンプレートはシンプルです。このテンプレートには、ヘッダー、検索項目、および検索結果を保持 するリストが含まれます。 1. 新しいスクリプトブロックを追加します。<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> 159 SmartSync を使用した Salesforce オブジェクトへのアク セス 検索ビューの追加 検索ビューの追加 画面のビューを作成するには、Backbone.View を拡張します。検索ビューの拡張で、テンプレートの読み込み、 サブビューとイベントハンドラの定義、およびビューを表示して SOQL 検索クエリを実行する機能の実装を行 います。 1. <body> ブロックで、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. 検索結果のリストを格納する UserListView という名前のサブビューをインスタンス化します。後で、 app.views.UserListView ビューを定義します。 initialize: function() { this.listView = new app.views.UserListView({model: this.model}); }, 4. 検索ページビューの render() 関数を作成します。アプリケーションの HTML コンテンツとしてテンプレー トを読み込むだけでビューを表示できます。検索項目に以前に入力した条件を復元し、<ul> 要素内のサブ ビューを表示します。 render: function(eventName) { $(this.el).html(this.template()); $(".search-key", this.el).val(this.model.criteria); this.listView.setElement($("ul", this.el)).render(); return this; }, 5. ユーザが検索項目に文字を入力したときに検索を実行する keyup イベントハンドラを追加します。 events: { "keyup .search-key": "search" }, search: function(event) { this.model.criteria = $(".search-key", this.el).val(); var soql = "SELECT Id, FirstName, LastName, SmallPhotoUrl, Title FROM User WHERE Name like '" + this.model.criteria + "%' ORDER BY Name LIMIT 25 "; this.model.fetch({config: {type:"soql", query:soql}}); } 160 SmartSync を使用した Salesforce オブジェクトへのアク セス 検索結果リストビューの追加 この関数は、SOQL クエリを定義します。次に、バッキングモデルを使用してそのクエリをサーバに送信し、 結果を取得します。 次に、完全な拡張を示します。 app.views.SearchPage = Backbone.View.extend({ template: _.template($("#search-page").html()), 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.criteria); this.listView.setElement($("ul", this.el)).render(); return this; }, events: { "keyup .search-key": "search" }, search: function(event) { this.model.criteria = $(".search-key", this.el).val(); var soql = "SELECT Id, FirstName, LastName, SmallPhotoUrl, Title FROM User WHERE Name like '" + this.model.criteria + "%' ORDER BY Name LIMIT 25 "; this.model.fetch({config: {type:"soql", query:soql}}); } }); 検索結果リストビューの追加 検索結果リストのビューでは、テンプレートは必要ありません。これは、単純にリスト項目ビューのコンテナで す。listItemViews メンバーのこれらのビューを追跡します。基盤となるコレクションが変更されると、それ 自体を再表示します。 1. <body> ブロックで、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(); }); 161 SmartSync を使用した Salesforce オブジェクトへのアク セス 検索結果リスト項目ビューの追加 3. render() 関数で、基盤となるコレクションのレコードに対応する新しい一連のリスト項目ビューを作成しま す。これらの各ビューは、リストのエントリにすぎません。後で app.views.UserListItemView を定義し ます。 this.listItemViews = _.map(this.model.models, function(model) { return new app.views.UserListItemView({model: model}); }); 4. リスト項目ビューをルート DOM 要素に追加します。 $(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 役職 1. <body> ブロックで、検索結果リスト項目のテンプレートを作成します。 <script id="user-list-item" type="text/template"> <img src="<%= SmallPhotoUrl %>" class="small-img" /> <div class="details-short"> <b><%= FirstName %> <%= LastName %></b><br/> Title<%= Title %> 162 SmartSync を使用した Salesforce オブジェクトへのアク セス 検索結果リスト項目ビューの追加 </div> </script> 2. テンプレートの直後に、検索結果リスト項目のビューを作成します。再度、Backbone.View をサブクラス化 し、tagName メンバーを定義して、ビュー全体をリストとして表示するように指定します。この手順の残り の部分で、すべてのコードを extend({}) ブロックに追加します。 app.views.UserListItemView = Backbone.View.extend({ tagName: "li", }); 3. user-list-item スクリプトの未加工のコンテンツを使用して、_.template() をコールし、テンプレート を読み込みます。 template: _.template($("#user-list-item").html()), 4. render() 関数で、モデルのデータを使用してテンプレートを表示します。 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(); } }); 163 SmartSync を使用した Salesforce オブジェクトへのアク セス ルータ ルータ Backbone ルータは、ビュー間の移動パスを定義します。ルータについての詳細は、「ルータとは?」を参照して ください。 1. <body> ブロックの終了タグの直前で、Backbone.Router を拡張してアプリケーションルータを定義します。 app.Router = Backbone.Router.extend({ }); この手順の残りの部分で、すべてのコードを extend({}) ブロックに追加します。 2. アプリケーションは 1 つの画面しかサポートしないので、1 つの「ルート」のみが必要になります。routes オブジェクトを追加します。 routes: { "": "list" }, 3. 検索結果のコレクションと検索ページビューを作成する initialize() 関数を定義します。 initialize: function() { Backbone.Router.prototype.initialize.call(this); // Collection behind search screen app.searchResults = new app.models.UserCollection(); app.searchView = new app.views.SearchPage({model: app.searchResults}); }, 4. このルートの項目のみを処理する list() 関数を定義します。リスト画面が表示されたときに、検索結果を取 得して検索ビューを表示します。 list: function() { app.searchResults.fetch(); $('#content').html(app.searchView.render().el); } 5. index.html をダブルクリックしてブラウザで開き、アプリケーションを実行します。 これで完了です。次に、アプリケーション全体を示します。 <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0; user-scalable=no" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <link rel="stylesheet" href="css/ratchet.css"/> <script src="jquery/jquery-2.0.0.min.js"></script> <script src="backbone/underscore-1.4.4.min.js"></script> <script src="backbone/backbone-1.0.0.min.js"></script> 164 SmartSync を使用した Salesforce オブジェクトへのアク セス ルータ <script src="cordova-2.3.0.js"></script> <script src="forcetk.mobilesdk.js"></script> <script src="cordova.force.js"></script> <script src="SmartSync.js"></script> </head> <body> <div id="content"></div> <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> <script id="user-list-item" type="text/template"> <img src="<%= SmallPhotoUrl %>" class="small-img" /> <div class="details-short"> <b><%= FirstName %> <%= LastName %></b><br/> Title<%= Title %> </div> </script> <script> var app = { models: {}, views: {} }; jQuery(document).ready(function() { document.addEventListener("deviceready",onDeviceReady,false); }); function onDeviceReady() { cordova.require("salesforce/plugin/oauth"). getAuthCredentials(appStart); } function appStart(creds) { console.log(JSON.stringify(creds)); Force.init(creds, null, null, cordova.require("salesforce/plugin/oauth").forcetkRefresh); app.router = new app.Router(); Backbone.history.start(); } // Models app.models.User = Force.SObject.extend({ sobjectType: "User", fieldlist: ["Id","FirstName","LastName", "SmallPhotoUrl","Title","Email","MobilePhone", "City"] }); app.models.UserCollection = Force.SObjectCollection.extend({ model: app.models.User }); // Views 165 SmartSync を使用した Salesforce オブジェクトへのアク セス ルータ app.views.SearchPage = Backbone.View.extend({ template: _.template($("#search-page").html()), 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.criteria); this.listView.setElement($("ul", this.el)).render(); return this; }, events: { "keyup .search-key": "search" }, search: function(event) { this.model.criteria = $(".search-key", this.el).val(); var soql = "SELECT Id, FirstName, LastName, SmallPhotoUrl, Title FROM User WHERE Name like '" + this.model.criteria + "%' ORDER BY Name LIMIT 25 "; this.model.fetch({config: {type:"soql", query:soql}}); } }); 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; } }); 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(); } }); // Router app.Router = Backbone.Router.extend({ routes: { "": "list" }, initialize: function() { 166 SmartSync を使用した Salesforce オブジェクトへのアク セス SmartSync サンプルアプリケーション Backbone.Router.prototype.initialize.call(this); // Collection behind search screen app.searchResults = new app.models.UserCollection(); app.searchView = new app.views.SearchPage({model: app.searchResults}); console.log("here"); }, list: function() { app.searchResults.fetch(); $('#content').html(app.searchView.render().el); } }); </script> </body> </html> SmartSync サンプルアプリケーション Salesforce Mobile SDK には、ハイブリッドアプリケーションでの SmartSync の使用方法を示すサンプルアプリケー ションが備えられています。Account Editor には、これらのサンプルの全機能が装備されています。いずれかの 単純なサンプルに切り替えるには、bootconfig.json ファイルの startPage プロパティを変更します。 iOS でのサンプルの実行 Salesforce Mobile SDK for iOS インストールディレクトリで、SalesforceMobileSDK.xcworkspace をダブルク リックして Xcode で開きます。Xcode で HybridShared/sampleApps/smartsync/AccountEditor.html を開き ます。 167 SmartSync を使用した Salesforce オブジェクトへのアク セス SmartSync サンプルアプリケーション Android でのサンプルの実行 Android では、コマンドプロンプトからサンプルを実行できます。Salesforce Mobile SDK for Android インストー ルディレクトリで、hybrid/SampleApps/AccountEditor ディレクトリに変更して次のコマンドを実行します。 ant debug ant installd メモ: local.properties ファイルが存在しないというエラーが発生した場合は、エラーメッセージに 表示されるディレクトリから次のコマンドを実行します。 %ANDROID_SDK%/tools/android update project -p . Eclipse でサンプルを実行するには、次のプロジェクトをワークスペースにインポートします。 • • • forcedroid/native/SalesforceSDK forcedroid/hybrid/SmartStore forcedroid/hybrid/SampleApps/AccountEditor Eclipse で作成が完了したら、Package Explorer で [AccountEditor] を Ctrl キーを押しながらクリックするか右ク リックしてから、[Run As (別のユーザとして実行)] > [Android Application (Android アプリケーション)] をクリッ クします。 168 SmartSync を使用した Salesforce オブジェクトへのアク セス SmartSync サンプルアプリケーション 169 SmartSync を使用した Salesforce オブジェクトへのアク セス User and Group Search のサンプル User and Group Search のサンプル User and Group Search は、最も単純な SmartSync サンプルアプリケーションです。ユーザおよびコラボレーショ ングループの検索と、一致するレコードのリスト表示を 1 つの画面で行うことができます。 サンプルを実行するには、external/shared/sampleApps/smartsync/bootconfig.json を編集します。 startPage を UserAndGroupSearch.html に変更します。 { "remoteAccessConsumerKey": "3MVG9Iu66FKeHhINkB1l7xt7kR8czFcCTUhgoA8Ol2Ltf1eYHOU4SqQRSEitYFDUpqRWcoQ2. dBv_a1Dyu5xa", "oauthRedirectURI": "testsfdc:///mobilesdk/detect/oauth/done", "oauthScopes": ["api","web"], "isLocal": true, "startPage": "UserAndGroupSearch.html", "errorPage": "error.html", "shouldAuthenticate": true, "attemptOfflineLoad": true "remoteAccessConsumerKey": "3MVG9Iu66FKeHhI2Ltf1eYHOU4SqQRSEitYFDUpqRWcoQ2. dBv_a1Dyu5xa", "oauthRedirectURI": "testsfdc:///mobilesdk/detect/oauth/done", "oauthScopes": ["api","web"], "isLocal": true, "startPage": "UserAndGroupSearch.html", "errorPage": "error.html", "shouldAuthenticate": true, "attemptOfflineLoad": true "remoteAccessConsumerKey": "3MVG9Iu66FKeHhINkB1l7xt7kR8czFcCTUhgoA8Ol2Ltf1eYHOU4SqQRSEitYFDUpqRWcoQ2. dBv_a1Dyu5xa", "oauthRedirectURI": "testsfdc:///mobilesdk/detect/oauth/done", "oauthScopes": ["api","web"], "isLocal": true, "startPage": "UserAndGroupSearch.html", "errorPage": "error.html", "shouldAuthenticate": true, "attemptOfflineLoad": true } iOS で Xcode からアプリケーションを実行するには、[実行] をクリックして AccountEditor プロジェクトを起動 します。ログイン後、検索ボックスに 2 文字以上を入力して、一致結果を確認します。 内部で実行される処理の確認 任意のエディタで UserAndGroupSearch.html を開きます。ファイルの主要なセクションは、次のとおりです。 • • • • • スクリプトの内容 テンプレート モデル ビュー ルータ スクリプトの内容 このサンプルには、SmartSync アプリケーション用のライブラリの標準リストが含まれています。 170 SmartSync を使用した Salesforce オブジェクトへのアク セス User and Group Search のサンプル • jQuery — http://jquery.com/ を参照してください。 • Underscore — Backbone に必要な JavaScript 用のユーティリティ関連のライブラリです。http://underscorejs.org/ を参照してください。 • Backbone — Web アプリケーションに構造を提供します。SmartSync Data Framework で使用されます。 http://backbonejs.org/ を参照してください。 • cordova-2.3.0.js — SalesforceMobileSDK で使用するすべてのハイブリッドアプリケーションに必要です。 • fastclick.js — 物理タップしてからクリックイベントが発生するまでの 300 ミリ秒の遅延を回避するため に使用されるライブラリです。https://github.com/ftlabs/fastclick を参照してください。 • stackrouter.js および auth.js — 3 つのすべてのサンプルアプリケーションで使用されるヘルパー JavaScript ライブラリです。 テンプレート このアプリケーションのテンプレートは、次のとおりです。 • search-page — 検索ページ全体のテンプレート • user-list-item — ユーザリスト項目のテンプレート • group-list-item — コラボレーショングループリスト項目のテンプレート モデル このアプリケーションでは、SearchCollection モデルが定義されます。 SearchCollection は Force.SObjectCollection クラスをサブクラス化し、Force.SObjectCollection は Backbone ライブラリの Collection クラスをサブクラス化します。その唯一のメソッドにより、fetch() メソッ ドで使用される SOSL クエリが設定され、コレクションが入力されます。 app.models.SearchCollection = Force.SObjectCollection.extend({ setCriteria: function(key) { this.config = {type:"sosl", query:"FIND {" + key + "*} IN ALL FIELDS RETURNING " + "CollaborationGroup (Id, Name, SmallPhotoUrl, MemberCount), " + "User (Id, FirstName, LastName, SmallPhotoUrl, Title ORDER BY Name) " + "LIMIT 25" }; } }); ビュー User and Group Search では、3 つのビューが定義されます。 SearchPage 検索ページには、モデルとして SearchCollection が使用されます。検索入力項目に変更があるかどうか を監視し、モデルを適宜更新します。 events: { "keyup .search-key": "search" }, search: function(event) { var key = $(".search-key", this.el).val(); if (key.length >= 2) { 171 SmartSync を使用した Salesforce オブジェクトへのアク セス User Search のサンプル this.model.setCriteria(key); this.model.fetch(); } } ListView 検索画面のリスト部分です。ListView でも、モデルとして Collection が指定され、Collection のレ コードごとに ListItemView オブジェクトが作成されます。 ListItemView データに基づいてユーザまたはグループのいずれかのテンプレートを選択して、1 つのリスト項目の詳細を 表示します。 ルータ このアプリケーションでは 1 つの画面しか定義されないため、ルータにはあまり意味はありません。 User Search のサンプル User Search は、User and Group Search より複雑なサンプルです。1 つの画面ではなく、2 つの画面が定義されま す。一致項目のリストが検索から返された場合、各項目をタップすると、基本情報の詳細画面が表示されます。 複数の画面が定義されるため、このサンプルではルータの使用についても示しています。 サンプルを実行するには、external/shared/sampleApps/smartsync/bootconfig.json を編集します。 startPage を UserSearch.html に変更します。 { "remoteAccessConsumerKey": "3MVG9Iu66FKeHhI2Ltf1eYHOU4SqQRSEitYFDUpqRWcoQ2.dBv_a1Dyu5xa", "oauthRedirectURI": "testsfdc:///mobilesdk/detect/oauth/done", "oauthScopes": ["api","web"], "isLocal": true, "startPage": "UserSearch.html", "errorPage": "error.html", "shouldAuthenticate": true, "attemptOfflineLoad": true } Xcode または Eclipse で AccountEditor を起動します。ログインを指示するプロンプトが表示された場合は、ログ インします。User and Group Search の場合と異なり、検索ボックスには 1 文字のみを入力して、検索結果の表示 を開始します。この理由は、サーバに対するクエリで SOSL ではなく SOQL がアプリケーションで使用される からです。 検索結果リストのエントリをタップすると、基本情報の詳細画面が表示されます。 内部で実行される処理の確認 任意のエディタで UserSearch.html ファイルを開きます。ファイルの主要なセクションは、次のとおりです。 • • • • スクリプトの内容 テンプレート モデル ビュー 172 SmartSync を使用した Salesforce オブジェクトへのアク セス • User Search のサンプル ルータ スクリプトの内容 このサンプルには、SmartSync アプリケーション用のライブラリの標準リストが含まれています。 • jQuery — http://jquery.com/ を参照してください。 • Underscore — Backbone に必要な JavaScript 用のユーティリティ関連のライブラリです。http://underscorejs.org/ を参照してください。 • Backbone — Web アプリケーションに構造を提供します。SmartSync Data Framework で使用されます。 http://backbonejs.org/ を参照してください。 • cordova-2.3.0.js — SalesforceMobileSDK で使用するすべてのハイブリッドアプリケーションに必要です。 • forcetk.mobilesdk.js — Rest API コールを行うための Force.com JavaScript ライブラリです。SmartSync に 必要です。 • cordova.force.js — Mobile SDK 2.0 では、このファイルによってすべての Force.com Cordova プラグインが 統合されます。SFHybridApp.js、SalesforceOAuthPlugin.js、および SmartStorePlugin.js ファイル に置き換わります。 • SmartSync.js — Mobile SDK SmartSync Data Framework です。 • fastclick.js — 物理タップしてからクリックイベントが発生するまでの 300 ミリ秒の遅延を回避するため に使用されるライブラリです。https://github.com/ftlabs/fastclick を参照してください。 • stackrouter.js および auth.js — 3 つのすべてのサンプルアプリケーションで使用されるヘルパー JavaScript ライブラリです。 テンプレート このアプリケーションのテンプレートは、次のとおりです。 • search-page — 検索ページ全体のテンプレート • user-list-item — ユーザリスト項目のテンプレート • user-page — ユーザ詳細ページのテンプレート モデル このアプリケーションでは、UserCollection および User という 2 つのモデルが定義されます。 UserCollection は Force.SObjectCollection クラスをサブクラス化し、Force.SObjectCollection は Backbone ライブラリの Collection クラスをサブクラス化します。その唯一のメソッドにより、fetch() メソッ ドで使用される SOQL クエリが設定され、コレクションが入力されます。 app.models.UserCollection = Force.SObjectCollection.extend({ model: app.models.User, fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl", "Title"], 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 " 173 SmartSync を使用した Salesforce オブジェクトへのアク セス User Search のサンプル }; } }); User は、SmartSync の Force.SObject クラスをサブクラス化します。User モデルでは、次の項目が定義されま す。 • モデルが表す sObject の種別を示す sobjectType 項目 (この場合は User) • サーバから取得する項目リストを含む fieldlist 項目 次にコードを示します。 app.models.User = Force.SObject.extend({ sobjectType: "User", fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl", "Title", "Email", "MobilePhone","City"] }); ビュー このサンプルでは、4 つのビューが定義されます。 SearchPage 検索ページ全体のビュー。モデルとして UserCollection が指定されます。検索入力項目に変更があるか どうかを監視し、search() 関数でモデルを適宜更新します。 events: { "keyup .search-key": "search" }, search: function(event) { this.model.setCriteria($(".search-key", this.el).val()); this.model.fetch(); } UserListView 検索画面のリスト部分のビュー。このビューでも、モデルとして UserCollection が指定され、 UserCollection オブジェクトのユーザごとに UserListItemView オブジェクトが作成されます。 UserListItemView 1 つのリスト項目のビュー。 UserPage ユーザの詳細を表示するビュー。 ルータ router クラスは、アプリケーションの 2 つの画面間の移動を処理します。このクラスでは、routes 項目を使用 して、ビューが router クラスメソッドに対応付けられます。 routes: { "": "list", "list": "list", "users/:id": "viewUser" }, 174 SmartSync を使用した Salesforce オブジェクトへのアク セス Account Editor のサンプル リストページから fetch() をコールして検索結果のコレクションを取得し、検索ページをビューに表示します。 list: function() { app.searchResults.fetch(); // Show page right away - list will redraw when data comes in this.slidePage(app.searchPage); }, ユーザ詳細ページから fetch() をコールしてユーザモデルを取得し、ユーザ詳細ページをビューに表示します。 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); } }); } Account Editor のサンプル Account Editor は、Mobile SDK 2.0 の最も複雑な SmartSync ベースのサンプルアプリケーションです。取引先を オンラインまたはオフラインで作成/編集/削除したり、競合の検出を示したりすることができます。 サンプルを実行する手順は、次のとおりです。 1. external/shared/sampleApps/smartsync/bootconfig.json に変更を加えた場合は、元のコンテンツに 戻します。 2. Account Editor を起動します。 このアプリケーションには、3 つの画面が含まれています。 • 取引先の検索 • 取引先の詳細 • 同期 アプリケーションを初めて起動すると、最後に使用した取引先をリストする取引先検索画面が表示されます。こ の画面では、次の操作を実行できます。 • 検索文字列を入力して、指定した文字列が名前に含まれている取引先を検索する。 • 取引先をタップして、取引先詳細画面を起動する。 • [作成] をタップして、空の取引先詳細画面を起動する。 • [オンライン] をタップして、オフラインにする。すでにオフラインになっている場合は、[オフライン] ボタ ンをタップして、オンラインに戻すことができます (デバイスを機内モードにして、オフラインにすることも できます)。 取引先詳細画面を起動するには、取引先検索画面で取引先レコードをタップします。選択した取引先の項目が、 詳細画面に表示されます。この画面では、次の操作を実行できます。 • 項目をタップして、値を変更する。 175 SmartSync を使用した Salesforce オブジェクトへのアク セス • Account Editor のサンプル [保存] をタップして、取引先を更新または作成する。入力規則エラーが発生すると、問題のある項目が強調 表示されます。 保存時にオンラインになっており、最後の取得以降にサーバのレコードが変更された場合は、リモートで変 更された項目について警告が表示されます。 [マージ] および [上書き] という他の 2 つのボタンを使用して、アプリケーションで変更をどのように保存す るかを制御できます。[上書き] をタップすると、画面に現在表示されているすべての値がサーバに保存され ます。[マージ] をタップすると、ユーザが変更した項目のみがサーバに保存され、ユーザが変更しない項目 についてはサーバで変更が継続されます。 • [削除] をタップして、取引先を削除する。 • [オンライン] をタップしてオフラインにするか、[オフライン] をタップしてオンラインにする。 同期画面を表示するには、[オンライン]をタップしてオフラインにしてから、取引先を作成、更新、または削除 します。[オフライン]を再度タップしてオンラインに戻すと、デバイスで変更したすべての取引先が同期画面に 表示されます。 ローカルの変更をサーバに保存するには、[n件のレコードを処理] をタップします。取引先の保存に失敗すると、 同期に失敗したことが表記されて取引先がリストに残ります。リスト内の任意の取引先をタップしてさらに編集 したり、ローカルで削除した取引先を復元したりできます。 内部で実行される処理の確認 このサンプルのソースコードを表示するには、HTML またはテキストエディタで AccountEditor.html を開き ます。 ファイルの主要なセクションは、次のとおりです。 • • • • • スクリプトの内容 テンプレート モデル ビュー ルータ スクリプトの内容 このサンプルには、SmartSync アプリケーション用のライブラリの標準リストが含まれています。 • jQuery — http://jquery.com/ を参照してください。 Underscore — Backbone に必要な JavaScript 用のユーティリティ関連のライブラリです。http://underscorejs.org/ を参照してください。 Backbone — Web アプリケーションに構造を提供します。SmartSync Data Framework で使用されます。 http://backbonejs.org/ を参照してください。 cordova-2.3.0.js — Salesforce Mobile SDK を使用するハイブリッドアプリケーションに必要です。 • forcetk.mobilesdk.js — REST API コールを行うための Force.com JavaScript ライブラリです。SmartSync • • • に必要です。 • • cordova.force.js — Mobile SDK 2.0 では、このファイルによってすべての Force.com Cordova プラグインが 統合されます。SFHybridApp.js、SalesforceOAuthPlugin.js、および SmartStorePlugin.js ファイル に置き換わります。 SmartSync.js — Mobile SDK SmartSync Data Framework です。 176 SmartSync を使用した Salesforce オブジェクトへのアク セス Account Editor のサンプル • fastclick.js — 物理タップしてからクリックイベントが発生するまでの 300 ミリ秒の遅延を回避するため • に使用されるライブラリです。https://github.com/ftlabs/fastclick を参照してください。 stackrouter.js および auth.js — 3 つのすべてのサンプルアプリケーションで使用されるヘルパー JavaScript ライブラリです。 テンプレート このアプリケーションのテンプレートは、次のとおりです。 • • • • 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 query if (!app.offlineTracker.get("isOnline")) { 177 SmartSync を使用した Salesforce オブジェクトへのアク セス Account Editor のサンプル ... } // Online else { ... } } }); 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; } // Online else { return (method == "read" ? Force.CACHE_MODE.CACHE_FIRST : Force.CACHE_MODE.SERVER_FIRST); } } }); OfflineTracker は、Backbone の Model クラスのサブクラスです。このクラスは、ブラウザのオフライン状況 を監視することによって、アプリケーションのオフライン状況を追跡します。ブラウザがオフラインであること が検出された場合は、アプリケーションが自動的にオフラインに切り替わります。ただし、オンラインになるの はユーザが要求した場合のみです。 次にコードを示します。 app.models.OfflineTracker = Backbone.Model.extend({ initialize: function() { 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 178 SmartSync を使用した Salesforce オブジェクトへのアク セス Account Editor のサンプル }, 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(); } AcountListView 検索画面のリスト部分のビュー。モデルとして AccountCollection が指定され、AccountCollection オ ブジェクトの取引先ごとに AccountListItemView オブジェクトが作成されます。 AccountListItemView リスト内の項目のビュー。 EditAccountPage 取引先詳細ページのビュー。このビューでは、いくつかのイベントを監視します。 179 SmartSync を使用した Salesforce オブジェクトへのアク セス Account Editor のサンプル イベントタイプ ターゲットコントロール ハンドラ関数名 クリック button-prev goBack 変更 set 以外 (任意の編集コントロール change が有効) クリック save save クリック merge saveMerge クリック overwrite saveOverwrite クリック toggleDelete toggleDelete 2 つのイベントハンドラ関数は、特に注意が必要です。change() 関数は、ユーザ編集をモデルに戻すため にビューでイベントターゲットがどのように使用されるかを表示します。 change: function(evt) { // apply change to model var 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); alert("Failed to delete account: " + (error.type === "RestError" ? error.details[0].message : "Remote change detected - delete aborted")); } }); } } SyncPage 同期ページのビュー。このビューでは、いくつかのイベントを監視します。 イベントタイプ コントロール ハンドラ関数名 クリック button-prev goBack 180 SmartSync を使用した Salesforce オブジェクトへのアク セス Account Editor のサンプル イベントタイプ コントロール ハンドラ関数名 クリック sync sync 画面がどのように表示されるかを確認するには、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() { 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); } }); 181 SmartSync を使用した Salesforce オブジェクトへのアク セス Account Editor のサンプル ルータ ルータが初期化されると、サンプル全体で使用される 2 つグローバルキャッシュが設定されます。 setupCaches: function() { // Cache for offline support app.cache = new Force.StoreCache("accounts", [ {path:"Name", type:"string"} ]); // Cache for conflict detection app.cacheForOriginals = new Force.StoreCache("original-accounts"); return $.when(app.cache.init(), app.cacheForOriginals.init()); }, グローバルキャッシュが設定されると、2 つの AccountCollection オブジェクトも設定されます。1 つは検索 画面用、もう 1 つは同期画面用です。 // Collection behind search screen app.searchResults = new app.models.AccountCollection(); // Collection behind sync screen app.localAccounts = new app.models.AccountCollection(); app.localAccounts.config = {type:"cache", cacheQuery: {queryType:"exact", indexPath:"__local__", matchKey:true, order:"ascending", pageSize:25}}; 最後に、Search、Sync、および EditAccount の各画面用にビューオブジェクトが作成されます。 // We keep a single instance of SearchPage / SyncPage and EditAccountPage app.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 in this.slidePage(app.searchPage); }, addAccount アクションは、空の取引先オブジェクトを作成し、その取引先の編集ページをビューに表示しま す。 addAccount: function() { app.editPage.model = new app.models.Account({Id: null}); this.slidePage(app.editPage); }, 182 SmartSync を使用した Salesforce オブジェクトへのアク セス Account Editor のサンプル 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(); // Show page right away - list will redraw when data comes in this.slidePage(app.syncPage); } 183 第 11 章 オフラインでのデータの安全な保存 トピック: • • • • • • • • • • SmartStore について ハイブリッドアプリケーションで の SmartStore の有効化 既存の Android アプリケーション への SmartStore の追加 スープの登録 スープからのデータの取得 スマート SQL クエリ カーソルの使用 データの操作 擬似 SmartStore の使用 NativeSqlAggregator サンプルアプ リケーション: ネイティブアプリ ケーションでの SmartStore の使用 モバイルデバイスの接続はいつでも失われる可能性があり、病院や飛 行機などの環境では接続が禁止されることがよくあります。このよう な状況に対処するには、モバイルアプリケーションがオフラインになっ ても引き続き動作するようにすることが重要です。 Mobile SDK は、モバイルデバイス向けの安全なマルチスレッドオフラ インストレージソリューションである SmartStore を使用します。 SmartStore では、デバイスがインターネットに接続されていなくても データの操作を続行できます。 184 オフラインでのデータの安全な保存 SmartStore について SmartStore について SmartStore は、単純な 1 つのテーブルのデータベースにデータを JSON ドキュメントとして保存します。この データベースのインデックスを定義したり、標準クエリを実装する SmartStore ヘルパーメソッドか、SmartStore のスマート SQL 言語を使用するカスタムクエリのいずれかを使用してデータをクエリしたりできます。 SmartStore は、StoreCache (Mobile SDK のキャッシュメカニズム) を使用して、オフライン同期および競合の解決 サービスを提供します。StoreCache を使用して、Salesforce データの操作を管理することをお勧めします。 メモ: 純粋な HTML5 アプリケーションは、オフライン情報をブラウザのキャッシュに保存します。ブ ラウザのキャッシュは Mobile SDK の一部ではないため、ここでは説明していません。SmartStore は、ス トレージ機能をデバイスで使用します。この方法には、ネイティブ開発またはハイブリッド開発が必要 です。 サンプルオブジェクト この章のコードスニペットでは、すべての Salesforce 組織で事前定義されている 2 つのオブジェクト (取引先と商 談) を使用しています。取引先と商談は主従関係にあり、取引先には複数の商談を含めることができます。 関連リンク オフラインキャッシュのための StoreCache の使用 競合検出 スマート SQL クエリ SmartStore のスープ SmartStore は、のオフラインデータを 1 つ以上のスープに保存します。スープとは、概念的にはオフラインで保 存またはクエリするデータレコードの論理的なコレクション (JSON オブジェクトで表される) です。Force.com では通常、スープはオフラインで保存する標準オブジェクトまたはカスタムオブジェクトに対応付けられます。 スープはアプリケーションにいくつでも保存できますが、本来は自己完結型データセットであるため、スープ間 には直接的な相関関係はありません。データ自体の保存に加え、データ内の項目に対応付けるインデックスを指 定して、データのクエリをさらに簡単にカスタマイズできます。 警告: SmartStore データは、本質的に揮発性です。有効期限は、認証済みユーザおよび OAuth トークンの状態 に関係しています。ユーザがアプリケーションからログアウトすると、そのユーザに関連付けられてい るスープデータは SmartStore によりすべて削除されます。同様に、OAuth 更新トークンが取り消される か期限切れになると、ユーザのアプリケーション状態がリセットされ、SmartStore のすべてのデータが 消去されます。アプリケーションの設計時には、SmartStore データの揮発性を十分に考慮してください。 この警告は、組織で更新トークンに短期の有効期限を設定している場合に特に重要です。 185 オフラインでのデータの安全な保存 SmartStore のデータ型 SmartStore のデータ型 SmartStore では、次のデータ型がサポートされます。 型 説明 integer 4 バイト (SDK 2.1 以前) または 8 バイト (SDK 2.2 以降) で保存される符号付き整数 floating 8 バイトの IEEE 浮動小数点数として保存される浮動小 数点値 string データベースエンコード (UTF-8) で保存されるテキス ト文字列 日付表現 日付表現 SmartStore は、日時の型を指定しません。これらの値の表記には次の表の SmartStore のデータ型を使用すること をお勧めします。 型 形式 説明 string ISO 8601 文字列 「YYYY-MM-DD HH:MM:SS.SSS」 floating ユリウス日数 グリニッジの紀元前 4714 年 11 月 24 日の正午からの予期的グレゴリオ暦 に応じた日数。この値には、小数で 表される部分的な日数を含めること ができます。 integer Unix 時間 1970-01-01 00:00:00 UTC からの秒数 ハイブリッドアプリケーションでの SmartStore の有効化 ハイブリッドアプリケーションでは、JavaScript から SmartStore にアクセスします。ハイブリッドモバイルアプ リケーションでオフラインアクセスを有効にするには、Visualforce または HTML ページに次の JavaScript ライブ ラリファイルを含める必要があります。 • cordova-x.x.x.js — Cordova ライブラリ (以前の PhoneGap)。 • cordova.force.js — Salesforce OAuth プラグインおよび SmartStore プラグインの JavaScript 部分が含まれ る。オフラインであるかどうかの判別など、ユーティリティタスクを実行するメソッドも含まれます。 Android アプリケーションでは、SmartStore は省略可能なコンポーネントです。iOS アプリケーションでは必須 です。Mobile SDK npm スクリプトを使用して SmartStore アプリケーションを作成する場合、次のようになりま す。 186 オフラインでのデータの安全な保存 既存の Android アプリケーションへの SmartStore の追加 • forceios create を使用して iOS ハイブリッドプロジェクトを作成する場合、これらのライブラリは自動 的に組み込まれます。 • プロンプトが表示される forcedroid create を使用して Android ハイブリッドプロジェクトを作成する場 合、SmartStore を使用するかどうか確認を求められたら、「yes」を指定します。 • コマンドラインパラメータが含まれる forcedroid create を使用する場合、省略可能な ––usesmartstore=true パラメータを指定します。 関連リンク Android プロジェクトの作成 iOS プロジェクトの作成 既存の Android アプリケーションへの SmartStore の追加 既存の Android プロジェクト (ハイブリッドまたはネイティブ) に SmartStore を追加する手順は、次のとおりで す。 1. SmartStore ライブラリプロジェクトをプロジェクトに追加します。Eclipse で、[プロジェクト] メニューから [プロパティ] を選択します。左パネルで Android を選択し、右側の [追加] をクリックします。 hybrid/SmartStore プロジェクトを選択します。 2. <projectname>App.java ファイルで、SalesforceSDKManager の代わりに SalesforceSDKManagerWithSmartStore クラスをインポートします。次のステートメントを置換します。 import com.salesforce.androidsdk.app.SalesforceSDKManager 置換後のステートメントは、次のとおりです。 import com.salesforce.androidsdk.smartstore.app.SalesforceSDKManagerWithSmartStore 3. <projectname>App.java ファイルで、SalesforceSDKManager ではなく SalesforceSDKManagerWithSmartStore クラスを拡張するようにアプリケーションクラスを変更します。 スープの登録 スープにアクセスするには、まず登録する必要があります。名前、インデックス指定、成功およびエラー条件を 通知するコールバック関数の名前を指定します。 navigator.smartstore.registerSoup(soupName, indexSpecs, successCallback, errorCallback) スープがまだ存在していない場合は、この関数で作成されます。 スープがすでに存在する場合は、登録すること で既存のスープにアクセスできます。スープがすでに存在するかどうかを確認するには、次の関数を使用しま す。 navigator.smartstore.soupExists(soupName, successCallback, errorCallback); 187 オフラインでのデータの安全な保存 スープの登録 スープには、そのエントリで検出された 1 つ以上の項目にインデックス付けされます。スープエントリでの挿 入、更新、削除操作は、スープインデックスで追跡されます。スープを登録する場合、少なくとも 1 つのイン デックス項目を常に指定します。たとえば、単純なキー/値の保存としてスープを使用している場合は、文字列 型の 1 つのインデックス指定を使用します。 indexSpecs indexSpecs 配列は、事前定義されたインデックス付けでスープを作成する場合に使用されます。 indexSpecs 配列のエントリは、スープのインデックス付け方法を指定します。各エントリは、path:type ペアで構成されま す。path はインデックス項目の名前、type は「string」、「integer」、または「floating」のいずれかです。イン デックスパスでは大文字と小文字が区別され、Owner.Name などの複合パスを含めることができます。 メモ: 特定の indexSpec で記述された項目にインデックスエントリが存在しないと、そのインデックス で追跡されなくなります。 "indexSpecs":[ { "path":"Name", "type":"string" } { "path":"Id", "type":"string" } { "path":"ParentId", "type":"string" } { "path":"lastModifiedDate", "type":"integer" } ] メモ: • • インデックスのタイプは、インデックスにのみ適用されます。インデックス付き項目 (「select {soup:path} from {soup}」など) をクエリすると、インデックス指定で指定したタイプが返されま す。 インデックス列には null 項目を含めることができます。 successCallback registerSoup の正常なコールバック関数は、1 つの引数 (スープ名) を取ります。 function(soupName) { alert("Soup " + soupName + " was successfully created"); }; スープが正常に作成されると、スープが準備完了であることを示す successCallback が返されます。トランザ クションが完了するまで待機し、他の操作を開始する前にコールバックを受け取ります。渡された名前でスープ を登録すると、正常なコールバック関数からスープが返されます。 188 オフラインでのデータの安全な保存 スープからのデータの取得 errorCallback registerSoup のエラーコールバック関数は、1 つの引数 (エラーの説明文字列) を取ります。 function(err) { alert ("registerSoup failed with error:" + err); } スープの作成時にエラーが発生する理由には、次のようなものがあります。 • • • スープ名が無効または不正である インデックスがない (少なくとも 1 つのインデックス指定が必要) データベースエラーなど、他の予期しないエラーが発生した 関連リンク SmartStore のデータ型 スープからのデータの取得 SmartStore には、クエリ文字列を作成する一連のヘルパーメソッドが備えられています。特定のレコードセット をクエリするには、クエリ指定に適した build* メソッドをコールします。必要に応じて、次の表に示すイン デックス項目、並び替え順、および絞り込みに使用する他のメタデータも定義できます。 パラメータ 説明 indexPath 名前、取引先番号、日付などの検索対象。 beginKey 省略可能。クエリ範囲の開始を定義するために使用されます。 endKey 省略可能。クエリ範囲の終了を定義するために使用されます。 order 省略可能。「昇順」または「降順」のいずれかです。 pageSize 省略可能。指定されていない場合、結果の Cursor.pageSize に収まるページサ イズがネイティブプラグインから返されます。 メモ: すべてのクエリは 1 つの述語の検索です。結合をサポートするのはスマート SQL クエリのみです。 すべてのクエリ buildAllQuerySpec(indexPath, order, [pageSize]) は、スープ内のすべてのエントリを返します。特定 の順序では並び替えられません。スープ内のすべてのエントリをスキャンする場合に、このクエリを使用しま す。 order と pageSize は省略可能で、デフォルトはそれぞれ昇順と 10 です。次のように指定できます。 • • • buildAllQuerySpec(indexPath) buildAllQuerySpec(indexPath, order) buildAllQuerySpec(indexPath, order, [pageSize]) ただし、buildAllQuerySpec(indexPath,[pageSize]) は指定できません。 189 オフラインでのデータの安全な保存 スープからのデータの取得 ページサイズについての詳細は、「カーソルの使用」を参照してください。 メモ: 基本的には、画面に表示するエントリ数に合わせて pageSize を設定します。円滑なスクロール表 示を行うには、実際に表示するエントリ数の 2 倍または 3 倍に値を増やします。 スマート SQL SELECT ステートメントを含むクエリ buildSmartQuerySpec(smartSql, [pageSize]) は、smartSql で指定されたクエリを実行します。この関数 では独自のスマート SQL SELECT ステートメントを指定するため、他のクエリファクトリ関数に比べて柔軟性 が高まります。「スマート SQL クエリ」を参照してください。 pageSize は省略可能であり、デフォルトは 10 です。 次に、さまざまな開発環境で SQL COUNT 関数をコールするスマート 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 }); 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 = SalesforceSDKManagerWithSmartStore.getInstance().getSmartStore(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select count(*) from {employees}", 1), 0); // result should be [[ n ]] if there are n employees Exact によるクエリ buildExactQuerySpec(indexPath, matchKey, [pageSize]) は、indexPath 値の特定の matchKey と完全 に一致するエントリを見つけます。特定の ID の子エントリを検索する場合に、このクエリを使用します。たと えば、状況別の商談を検索できます。ただし、結果の順序は指定できません。 ID によって子を取得するサンプルコードは、次のとおりです。 var querySpec = navigator.smartstore.buildExactQuerySpec(“sfdcId”, “some-sfdc-id”); navigator.smartstore.querySoup(“Catalogs”, querySpec, function(cursor) { // we expect the catalog to be in: cursor.currentPageOrderedEntries[0] }); 親 ID によって子を取得するサンプルコードは、次のとおりです。 var querySpec = navigator.smartstore.buildExactQuerySpec(“parentSfdcId”, “some-sfdc-id); navigator.smartstore.querySoup(“Catalogs”, querySpec, function(cursor) {}); 190 オフラインでのデータの安全な保存 スープからのデータの取得 Range によるクエリ buildRangeQuerySpec(indexPath, beginKey, endKey, [order, pageSize]) は、indexPath の値が beginKey と endKey で定義された範囲内にあるエントリを見つけます。整数として保存された日付範囲など、 数値範囲で検索する場合に、この関数を使用します。 order と pageSize は省略可能で、デフォルトはそれぞれ昇順と 10 です。次のように指定できます。 • • • buildRangeQuerySpec(indexPath, beginKey, endKey) buildRangeQuerySpec(indexPath, beginKey, endKey, order) buildRangeQuerySpec(indexPath, beginKey, endKey, order, pageSize) ただし、buildRangeQuerySpec(indexPath, beginKey, endKey, pageSize) は指定できません。 beginKey と endKey に null 値を渡すと、範囲無期限の検索を実行できます。 • endKey に null を渡すと、indexPath が beginKey 以下の項目のすべてのレコードが検出されます。 • beginKey に null を渡すと、indexPath が endKey 以下の項目のすべてのレコードが検出されます。 • beginKey と endKey の両方に null を渡すと、すべてのエントリに対するクエリと同じ結果になります。 Like によるクエリ buildLikeQuerySpec(indexPath, likeKey, [order, pageSize]) は、indexPath の値が指定の likeKey に似ているエントリを見つけます。キーワードで開始する用語を検索するには「foo%」、キーワードで終了する 用語を検索するには「%foo」、indexPath 値のどこかにあるキーワードを検索するには「%foo%」をそれぞれ使 用できます。 一般検索および名前の部分一致を行う場合に、この関数を使用します。order と pageSize は省略 可能で、デフォルトはそれぞれ昇順と 10 です。 メモ: Like によるクエリは、クエリメソッドの中で最も低速です。 クエリの実行 クエリは非同期に実行され、JavaScript コールバックにカーソルが返されます。正常なコールバックの形式は、 function(cursor) です。クエリ指定を querySoup メソッドに渡すには、querySpec パラメータを使用しま す。 navigator.smartstore.querySoup(soupName,querySpec,successCallback,errorCallback); 主キーによる個々のスープエントリの取得 すべてのスープエントリには、一意の内部 ID (スープ内のすべてのエントリを保持する内部テーブルにおける主 キー) が自動的に与えられます。この ID 項目は、スープエントリで _soupEntryId 項目として使用できます。 スープエントリは、retrieveSoupEntries メソッドを使用して _soupEntryId で検索できます。返される順序 は保証されず、エントリが削除されている場合は、結果の配列に含まれません。このメソッドでは、スープエン トリを最も速く取得できますが、使用できるのは _soupEntryId がわかっている場合のみです。 navigator.smartStore.retrieveSoupEntries(soupName, indexSpecs, successCallback, errorCallback) 191 オフラインでのデータの安全な保存 スマート SQL クエリ スマート SQL クエリ Salesforce Mobile SDK バージョン 2.0 以降では、自由形式の SELECT ステートメント用に SmartStore でスマート SQL クエリ言語がサポートされます。スマート SQL クエリでは、スープおよびスープ項目の参照用に、標準 SQL SELECT の文法が他の記述子と組み合わされます。これにより、結合の使用を含め、制御および柔軟性が 最大限に高まります。スマート SQL では、標準 SQL SELECT 構造がすべてサポートされます。 スマート SQL の制限 スマート SQL でサポートされるのは、SELECT ステートメントおよびインデックス付きパスのみです。 構文 構文は標準 SQL SELECT の仕様と同じですが、次の点で違いがあります。 使用方法 構文 列を指定する {<soupName>:<path>} テーブルを指定する {<soupName>} スープエントリの JSON 文字列全体 {<soupName>:_soup} を参照する 内部スープエントリ ID を参照する {<soupName>:_soupEntryId} 最終更新日を参照する {<soupName>:_soupLastModifiedDate} サンプルクエリ Employees および Departments という名前の 2 つのスープについて考えます。Employees スープには、次の標準項 目が含まれています。 • 名 (firstName) • 姓 (lastName) • 部署コード (deptCode) • 従業員 ID (employeeId) • マネージャ ID (managerId) Departments スープには、次の項目が含まれています。 • 名 (name) • 部署コード (deptCode) 次に、これらのスープを使用した基本的なスマート SQL クエリをいくつか示します。 select {employees:firstName}, {employees:lastName} from {employees} order by {employees:lastName} select {departments:name} from {departments} order by {departments:deptCode} 192 オフラインでのデータの安全な保存 カーソルの使用 結合 スマート 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 e where 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} NativeSqlAggregator サンプルアプリケーションには、集計関数や結合用のスマート SQL サポートを含め、SmartStore のネイティブ実装が完全に装備されています。 関連リンク NativeSqlAggregator サンプルアプリケーション: ネイティブアプリケーションでの SmartStore の使用 カーソルの使用 クエリから返される結果が大きすぎて、読み込めない場合があります。代わりに、クエリ結果の小さなサブセッ ト (単一ページ) のみがネイティブ領域から JavaScript 領域にいつでもコピーされます。クエリを実行すると、ク エリ結果のリストでページ移動する方法を提供するカーソルオブジェクトがネイティブ領域から返されます。 JavaScript コードで前後のページに移動して、目的のページを JavaScript 領域にコピーできます。 メモ: 上級ユーザ向け: カーソルはデータのスナップショットではなく、動的です。スープに変更を加え てからカーソルのページ移動を開始すると、その変更が表示されます。カーソルで保持されるデータは、 元のクエリと結果セットでの現在の位置のみです。カーソルを移動すると、クエリが再度実行されます。 193 オフラインでのデータの安全な保存 データの操作 このため、新しく作成されたスープエントリを返すことができます (元のクエリの結果が返されている場 合)。 次のカーソル関数を使用して、クエリ結果を移動します。 • 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 つの引数 (更新後のカーソル) を指定します。 データの操作 挿入、更新、および削除するスープエントリを追跡するために、SmartStore では次の項目が各エントリに追加さ れます。 • _soupEntryId — この項目は、特定のスープのテーブルに含まれるスープエントリの主キーです。 • _soupLastModifiedDate — 1/1/1970 からのミリ秒数です。 ◊ JavaScript 日付に変換するには、new Date(entry._soupLastModifiedDate) を使用します。 ◊ 日付を 1/1/1970 を起点とした対応するミリ秒数に変換するには、date.getTime() を使用します。 スープエントリを挿入または更新すると、これらの項目が SmartStore で自動的に設定されます。特定のエントリ を削除または取得すると、そのエントリを _soupEntryId で参照できます。 スープエントリの挿入または更新 指定されたスープエントリに _soupEntryId スロットが設定済みの場合、そのスロットで識別されるエントリは スープ内で更新されます。エントリに _soupEntryId スロットが存在しないか、スロットの値が既存のスープエ ントリと一致しない場合は、スープがエントリに追加 (挿入) され、_soupEntryId スロットが上書きされます。 メモ: _soupEntryId または _soupLastModifiedDate の値は、自分自身で操作しないでください。 エントリの挿入または更新には、upsertSoupEntries メソッドを使用します。 navigator.smartStore.upsertSoupEntries(soupName, entries[], successCallback, errorCallback) soupName は対象スープの名前であり、entries はスープのデータ構造と一致する 1 つ以上のエントリの配列で す。successCallback パラメータと errorCallback パラメータは、registerSoup のパラメータのように動作 194 オフラインでのデータの安全な保存 データの操作 します。ただし、upsertSoupEntries の正常なコールバックは、新しいレコードが挿入されたか、既存のレコー ドが更新されたことを示します。 外部 ID を使用した更新/挿入 スープエントリが外部システムのデータを反映している場合、外部システムの ID (主キー) を使用してそのエン ティティを参照する必要がある場合があります。そのため、外部 ID を使用した更新/挿入がサポートされていま す。更新/挿入を実行する場合、任意のインデックス項目を外部 ID 項目として指定できます。SmartStore では、 指定された項目と同じ値を持つ既存のスープエントリが検索され、次の結果が得られます。 • • • 同じ値を持つ項目が存在しないと、新しいスープエントリが作成されます。 外部 ID が見つかると、更新されます。 外部 ID と一致する項目が複数存在すると、エラーが返されます。 新しいエントリをローカルで作成する場合は、通常の更新/挿入を使用します。新しいエントリを後からサーバ にアップロードするときにクエリできる値に、外部 ID 項目を設定します。 サーバから取得したデータでエントリを更新する場合は、外部 ID を使用して更新/挿入します。これにより、同 じリモートレコードに対してスープエントリが重複しないことが保証されます。 次のサンプルコードでは、レコードがサーバにまだ存在しないため、id 項目の値に new を選択しています。オ ンラインになったら、ローカルにのみ存在するレコードをクエリ (id == "new" であるレコードを検索) して、 それをサーバにアップロードできます。レコードの実際の ID がサーバから返されると、その id 項目をローカ ルで更新できます。サーバでまだ作成されていないカタログに属する製品を作成する場合、parentSoupEntryId 項目を使用して、カタログとの関係を取得できます。カタログがサーバで作成されたら、ローカルレコードの parentExternalId 項目を更新します。 次のコードには、サンプルシナリオが含まれています。まず、upsertSoupEntries をコールして、新しいスー プエントリを作成します。コールバックに成功したら、新しく割り当てられたスープエントリ ID を持つ新しい レコードを取得します。次に、説明を変更し forcetk.mobilesdk メソッドをコールして、サーバで新しいアカ ウントを作成し、更新します。最後のコールは、外部 ID を使用した更新/挿入を示します。コードを見やすくす るため、エラーコールバックは指定していません。また、SmartStore コールはすべて非同期であるため、実際の アプリケーションでは、前のステップのコールバックで各ステップを実行する必要があります。 // Specify data for the account to be created var acc = {id: "new", Name: "Cloud Inc", Description: "Getting started"}; // Create account in SmartStore // This upsert does a "create" because the acc has no _soupEntryId field navigator.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 memory acc["Description"] = "Just shipped our first app "; // Update account in SmartStore // This does an "update" because acc has a _soupEntryId field navigator.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 SmartStore navigator.smartstore.upsertSoupEntries("accounts", [ acc ]); 195 オフラインでのデータの安全な保存 擬似 SmartStore の使用 }); // Update account's description in memory acc["Description"] = "Now shipping for iOS and Android"; // Update account's description on server // Sync client -> server for entities existing on server forcetkClient.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 client forcetkClient.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"); }); スープエントリの削除 エントリは非同期でスープから削除され、コールバックがコールされます (成功または失敗の情報が表示されま す)。soupEntryIds は、削除するエントリの _soupEntryId 値のリストです。 navigator.smartStore.removeFromSoup(soupName, soupEntryIds, successCallback, errorCallback) スープの削除 スープを削除するには、removeSoup() をコールします。ユーザがサインアウトすると、スープが自動的に削除 されます。 navigator.smartstore.removeSoup(soupName,successCallback,errorCallback); 擬似 SmartStore の使用 コンテナ外で実行しながら SmartStore を使用するコードの開発とテストを容易にするため、エミュレートされた SmartStore を使用できます。 MockSmartStore は、データをローカルストレージ (または必要に応じてメモリのみ) に保存する SmartStore の JavaScript 実装です。 external/shared/test ディレクトリには、次のファイルがあります。 • MockCordova.js — コンテナ外でプラグインのテストのみを目的とする、Cordova 関数の最小限の実装。 Cordova プラグインコールを受信します。 • MockSmartStore.js — コンテナ外での開発およびテストのみを目的とする、SmartStore の JavaScript 実装。 また、SmartStore Cordova プラグインコールを受信し、MockSmartStore を使用して処理します。 SmartStore を使用してアプリケーションを開発する場合、次の変更を加え、コンテナ外でアプリケーションをテ ストします。 • cordova-x.x.x.js ではなく MockCordova.js を含める。 • cordova.force.js の後に MockSmartStore.js を含める。 196 オフラインでのデータの安全な保存 擬似 SmartStore の使用 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}) ◊ SELECT count(*) FROM {soupName} MockSmartStore では、build*QuerySpec() 関数で処理される、より単純なタイプのスマート SQL ス テートメントは直接サポートされていません。代わりに、目的に合ったクエリ指定の関数が使用され ます。 関連リンク スープからのデータの取得 197 オフラインでのデータの安全な保存 NativeSqlAggregator サンプルアプリケーション: ネイティ ブアプリケーションでの SmartStore の使用 NativeSqlAggregator サンプルアプリケーション: ネイティブア プリケーションでの SmartStore の使用 NativeSqlAggregator アプリケーションは、ネイティブアプリケーションで SmartStore を使用する方法を示しま す。また、SUM や COUNT などの集計関数を含め SQL に似た複雑なクエリを行ったり、SmartStore 内の異なる スープを結合したりする機能も示します。 スープの作成 Salesforce オブジェクトを SmartStore に保存するための最初のステップは、オブジェクトにスープを作成するこ とです。スープを登録する関数コールは、2 つの引数 (スープの名前とインデックス指定) を受け付けます。イン デックス付けでは、3 つのデータ型 (string、integer、および floating decimal) をサポートしています。次の例では、 Name、Id、および OwnerId の各項目でインデックス付けして Account オブジェクトのスープを初期化する方法 を示しています。 Android: SalesforceSDKManagerWithSmartStore sdkManager = SalesforceSDKManagerWithSmartStore.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: SFSmartStore *store = [SFSmartStore sharedStoreWithName:kDefaultSmartStoreName]; NSArray *keys = [NSArray arrayWithObjects:@"path", @"type", nil]; NSArray *nameValues = [NSArray arrayWithObjects:@"Name", kSoupIndexTypeString, nil]; NSDictionary *nameDictionary = [NSDictionary dictionaryWithObjects:nameValues forKeys:keys]; NSArray *idValues = [NSArray arrayWithObjects:@"Id", kSoupIndexTypeString, nil]; NSDictionary *idDictionary = [NSDictionary dictionaryWithObjects:idValues forKeys:keys]; NSArray *ownerIdValues = [NSArray arrayWithObjects:@"OwnerId", kSoupIndexTypeString, nil]; NSDictionary *ownerIdDictionary = [NSDictionary dictionaryWithObjects:ownerIdValues forKeys:keys]; NSArray *accountIndexSpecs = [[NSArray alloc] initWithObjects:nameDictionary, idDictionary, ownerIdDictionary, nil]; [store registerSoup:@"Account" withIndexSpecs:accountIndexSpecs]; 198 オフラインでのデータの安全な保存 NativeSqlAggregator サンプルアプリケーション: ネイティ ブアプリケーションでの SmartStore の使用 スープへのデータの保存 スープを作成したら、次にデータをスープに保存します。次の例の account は、Account オブジェクトの単一レ コードを表します。Android では、account の種別は JSONObject になります。iOS では、種別 が NSDictionary になります。 Android: SmartStore smartStore = sdkManager.getSmartStore(); smartStore.upsert("Account", account); iOS: SFSmartStore *store = [SFSmartStore sharedStoreWithName:kDefaultSmartStoreName]; [store upsertEntries:[NSArray arrayWithObject:account] toSoup:@"Account"]; SmartStore に対するクエリの実行 Mobile SDK 2.0 以降では、SQL に似た高度なクエリを、複数のスープにまたがる SmartStore に対して実行でき ます。SmartStore クエリの構文は標準 SQL の構文に似ていますが、細かい点で多少の違いがあります。スープ 名とインデックス項目間の区切り文字として、コロン (「:」) が使用されます。<soup-name>:<field-name> ペ アはそれぞれ 1 組の中括弧で囲まれます。「スマート SQL クエリ」を参照してください。 次に、SmartStore に対して実行する集計クエリの例を示します。 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} このクエリは、2 つのスープ (Account と Opportunity) 間の暗黙的な結合を表します。返される内容は次のとおり です。 • • • • • Account の名前 Account に関連付けられた Opportunity 数 その Account の各 Opportunity に関連付けられたすべての金額の合計 その Account の 1 つの Opportunity に関連付けられた金額の平均 Account 名によるグルーピング 次のコードスニペットは、ネイティブアプリケーション内からこのようなクエリを実行する方法を示していま す。この例では、smartSql がクエリ、pageSize が要求されたページサイズです。pageIndex 引数は、どの結 果ページを返すかを指定します。 Android: QuerySpec querySpec = QuerySpec.buildSmartQuerySpec(smartSql, pageSize); JSONArray result = smartStore.query(querySpec, pageIndex); 199 オフラインでのデータの安全な保存 NativeSqlAggregator サンプルアプリケーション: ネイティ ブアプリケーションでの SmartStore の使用 iOS: SFSmartStore *store = [SFSmartStore sharedStoreWithName:kDefaultSmartStoreName]; SFQuerySpec *querySpec = [SFQuerySpec newSmartQuerySpec:queryString withPageSize:pageSize]; NSArray *result = [store queryWithQuerySpec:querySpec pageIndex:pageIndex]; 200 第 12 章 転送通知と Mobile SDK トピック: • • • 転送通知について Android での転送通知の使用 iOS での転送通知の使用 Salesforce からの転送通知は、モバイルユーザが組織内の重要な動向を 常に把握しておくのに役立ちます。Summer '14 で正式リリースされた Salesforce Mobile 転送通知サービスでは、コードを実装する前にモバイ ル転送通知を設定およびテストできます。本番環境でモバイル通知を 受信するには、Mobile SDK アプリケーションでモバイル OS プロバイ ダの登録プロトコルを実装して、受信通知を処理します。Mobile SDK では、大部分の登録タスクが内部的に実装されているため、コーディ ング作業を最小限に抑えることができます。 201 転送通知と Mobile SDK 転送通知について 転送通知について Salesforce Mobile 転送通知サービスを使用すると、ネイティブモバイルアプリケーションで転送通知を開発およ びテストできます。ネイティブ iOS アプリケーションとネイティブ Android アプリケーションの Salesforce 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 は、ランタイム登録を透過的に処理します。 組織のモバイル転送通知の設定方法についての詳細は、『Salesforce Mobile Push Notifications Implementation Guide』 を参照してください。Summer '14 の正式リリース後は、このドキュメントは、 https://help.salesforce.com/help/doc/en/salesforce_mobile_push_notifications_implementation_guide.pdf でご覧いただけ ます。 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 エミュレータでは動作しません。 まず、アプリケーションに Google API プロジェクトを作成します。プロジェクトでは、GCM for Android 機能 が有効になっている必要があります。プロジェクトの設定手順については、 http://developer.android.com/google/gcm/gs.html を参照してください。 Google API プロジェクトの設定プロセスでは、アプリケーションのキーが作成されます。プロジェクトの設定が 完了したら、GCM キーを接続アプリケーションの設定に追加する必要があります。 メモ: 転送通知の登録は、OAuth ログインフローの最後に行われます。そのため、ユーザが Salesforce 組 織にログインするまで、転送通知はアプリケーションで受信されません。 202 転送通知と Mobile SDK GCM (Android) 用に接続アプリケーションを設定する 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">35123627573</string> • assets/www/bootconfig.json は次のようになります (ハイブリッドアプリケーションの場合)。 "androidPushNotificationClientId": "35123627573" この値は、Android デバイスに対して転送通知の送信が承認された Google プロジェクトのプロジェクト番号 を表します。 Mobile SDK はこの値を自動的に読み取り、それを使用して、Salesforce 接続アプリケーションに対してデバイ スを登録します。この検証により、Salesforce から接続アプリケーションに通知を送信できます。また、ログ アウト時には転送通知用のデバイスが Mobile SDK で自動的に登録解除されます。 2. PushNotificationInterface を実装するアプリケーションでクラスを作成します。 PushNotificationInterface は、転送通知を処理するための Mobile SDK Android インターフェースです。 203 転送通知と Mobile SDK iOS での転送通知の使用 PushNotificationInterface には、onPushMessageReceived(Bundle message) という 1 つのメソッド があります。 public interface PushNotificationInterface { public void onPushMessageReceived(Bundle message); } このメソッドでは、転送通知を表示または破棄するカスタム機能を実装します。 3. Application サブクラスの onCreate() メソッドで、PushNotificationInterface の実装を渡して SalesforceSDKManager.setPushNotificationReceiver() メソッドをコールします。 SalesforceSDKManager.initNative() コールの直後に、このメソッドをコールします。次に例を示しま す。 @Override public 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 秘密鍵をファイルにエクスポートします。 iOS Developer Program のアプリケーション ID iOS Developer Member Center で、アプリケーションの ID を作成し、CSR ファイルを使用して証明書を生成 します。次に、OpenSSL を使用して、この証明書と秘密鍵のファイルを組み合わせて .p12 ファイルを作 成します。このファイルは、接続アプリケーションを後で設定するときに必要になります。 204 転送通知と Mobile SDK APNS (iOS) 用に接続アプリケーションを設定する 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 ファイルとそのパスワードを追加します。 205 転送通知と Mobile SDK コードの変更 (iOS) メモ: 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, // 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; } 206 転送通知と Mobile SDK コードの変更 (iOS) 登録に成功すると、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]; 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); } 207 第 13 章 モバイルアプリケーションでの認証、セキュリティ、ID トピック: • • • • OAuth の用語 OAuth2 認証フロー 接続アプリケーション OAuth 2.0 サイトおよび Force.com サイトを使用したポータル認証 モバイルデバイスで実行されているエンタープライズアプリケーショ ンにとって、安全な認証は不可欠です。OAuth2 は、ユーザのデータ へのアクセスに安全な認証を許可する業界標準のプロトコルです。ユー ザ名およびパスワードを渡す必要はありません。OAuth は、ソフト ウェアアクセスのバレットキーと呼ばれることがよくあります。バレッ トキーとは、自動車の特定の部分のみ開けられるキーのことで、トラ ンクやダッシュボードの小物入れなどは開けられないようになってい ます。 モバイルアプリケーションの開発者は、Salesforce OAuth2 の実装をす ばやく簡単に組み込むことができます。実装では HTML ビューを使 用してユーザ名とパスワードが収集され、それがサーバに送信されま す。セッショントークンが返され、今後のやり取りのためにデバイス に保存されます。 Salesforce 接続アプリケーションは、モバイルデバイスを Salesforce に 接続するための主要な手段です。接続アプリケーションにより、開発 者と管理者は、アプリケーションの接続方法およびアクセス権を付与 するユーザを制御できます。たとえば、接続アプリケーションを特定 のユーザに制限したり、IP 範囲の設定または緩和などを行うことがで きます。 208 モバイルアプリケーションでの認証、セキュリティ、ID OAuth の用語 OAuth の用語 アクセストークン ユーザの Salesforce ログイン情報を使用する代わりに、保護されたリソースへのユーザのアクセスを許可す るためにコンシューマにより使用される値。アクセストークンはセッション ID であり、直接使用できま す。 認証コード エンドユーザによって付与されるアクセスを表示する、有効期間の短いトークンです。認証コードは、ア クセストークンと更新トークンを取得するために使用されます。 接続アプリケーション OAuth プロトコルを使用して Salesforce ユーザと外部アプリケーションの両方を検証する、Salesforce の外部 アプリケーションです。リモートアクセスアプリケーションに置き換わります。 コンシューマ鍵 Salesforce で識別するためのコンシューマにより使用される値。client_id とも呼ばれます。 更新トークン 新しいアクセストークンを取得するためにコンシューマが使用するトークン。エンドユーザがアクセスを 再度承認する必要がありません。 リモートアクセスアプリケーション (廃止) リモートアクセスアプリケーションとは、OAuth プロトコルを使用して Salesforce ユーザと外部アプリケー ションの両方を検証する、Salesforce の外部アプリケーションです。リモートアクセスアプリケーションは、 Salesforce ヘルプの 接続アプリケーションとして実装されています。リモートアクセスアプリケーションは 廃止され、接続アプリケーションになりました。 OAuth2 認証フロー 認証フローは、デバイスにおける認証状態によって異なります。 初回の認証フロー 1. 2. 3. 4. 5. 6. モバイルアプリケーションを開きます。 認証ダイアログ/ウィンドウ/フロート表示が画面に表示されます。 ユーザ名とパスワードを入力します。 アプリケーションでセッション ID を受信します。 アプリケーションへのアクセスを許可します。 アプリケーションが起動します。 継続的な認証 1. モバイルアプリケーションを開きます。 209 モバイルアプリケーションでの認証、セキュリティ、ID OAuth 2.0 ユーザエージェントフロー 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(); をコールし、ブラウザの履歴から のコールバックを削除します。 210 モバイルアプリケーションでの認証、セキュリティ、ID OAuth 2.0 更新トークンフロー 1. クライアントアプリケーションでは、アプリケーションを認証および承認するために、ユーザを Salesforce に 移動します。 2. ユーザは常に、この認証フローへのアクセスを承認する必要があります。アクセス承認後、アプリケーショ ンは Salesforce からのコールバックを受信します。 コンシューマがアクセストークンを入手したら、そのアクセストークンを使用して、エンドユーザの代わりに データにアクセスし、更新トークンを取得できます。更新トークンを使用すると、アクセストークンが何らかの 理由で無効になった場合に、コンシューマが新しいアクセストークンを取得できます。 OAuth 2.0 更新トークンフロー コンシューマがアクセスを認証されたら、トークンを更新して新しいアクセストークン (セッション ID) を取得 できます。これは、コンシューマが Web サーバまたはユーザエージェントフローのいずれかを使用して、更新 トークンをすでに受信した場合のみに実行できます。アクセストークンを無効にするタイミングおよび新しい トークンを適用するタイミングを決定するのは、コンシューマです。べアラーフローは、コンシューマが更新 トークンフローを受信した後でのみ使用できます。 更新トークン認証フローの手順は、次のとおりです。各ステップの詳細は次のとおりです。 1. コンシューマは既存の更新トークンを使用して、新しいアクセストークンを要求します。 2. 要求の確認後、Salesforce からクライアントに応答が送信されます。 メモ: Mobile SDK アプリケーションでは、SmartStore 機能を使用してデータをオフラインで使用するために ローカルに保存できます。SmartStore データは、本質的に揮発性です。有効期限は、認証済みユーザお よび OAuth トークンの状態に関係しています。ユーザがアプリケーションからログアウトすると、その ユーザに関連付けられているスープデータは SmartStore によりすべて削除されます。同様に、OAuth 更 新トークンが取り消されるか期限切れになると、ユーザのアプリケーション状態がリセットされ、SmartStore 211 モバイルアプリケーションでの認証、セキュリティ、ID 範囲パラメータの値 のすべてのデータが消去されます。アプリケーションの設計時には、SmartStore データの揮発性を十分 に考慮してください。この警告は、組織で更新トークンに短期の有効期限を設定している場合に特に重 要です。 範囲パラメータの値 OAuth では、サーバおよびクライアントの両方に範囲設定が必要です。サーバ側とクライアント側間の同意に よって、範囲に関する契約が定義されます。 • サーバ側 — Salesforce サーバの接続アプリケーションで、範囲権限を定義します。この設定により、Mobile SDK アプリケーションなど、クライアントアプリケーションが要求できる範囲が決まります。ほとんどのネ イティブ Mobile SDK アプリケーションでは、refresh_token および api で十分です。 • クライアント側 — Mobile SDK アプリケーションで範囲要求を定義します。クライアントの範囲要求は、接 続アプリケーションの範囲権限のサブセットである必要があります。 サーバ側の設定 scope パラメータによって、Salesforce 組織でクライアントアプリケーションがアクセスできる項目を細かく設定 できます。scope の有効値は次のとおりです。 値 説明 api REST API や Bulk API などの API を使用して、現在のログインユーザの取引先へ のアクセスを許可します。この値には、Chatter REST API リソースへのアクセスを 許可する chatter_api も含まれます。 chatter_api Chatter REST API リソースへのアクセスのみを許可します。 full ログインユーザがアクセスできるすべてのデータへのアクセスを許可します。full は更新トークンを返しません。更新トークンを取得するには、refresh_token の 範囲を明示的に要求する必要があります。 id ID URL サービスへのアクセスを許可します。profile、email、address、phone を要求すれば、id を使用した場合と同じ結果を個別に得られます。これらの結果 はすべて一致します。 openid OpenID Connect アプリケーションの現在のログインユーザの一意の識別子へのア クセスを許可します。 アクセストークンの他にも、「OpenID Connect の仕様」に従って、OAuth 2.0 ユー ザエージェントフローおよび OAuth 2.0 Web サーバ認証フローで openid 範囲を使 用して、署名付き ID トークンを再度取得できます。 refresh_token 更新トークンを受信できる場合に、それを返すように指定します。これにより、 ユーザがオフラインのときにアプリケーションがユーザのデータを操作できます。 これは、offline_access を要求した場合と同じ意味になります。 visualforce Visualforce ページへのアクセスを許可します。 web Web で access_token を使用することを許可します。これには visualforce も含 まれ、Visualforce ページへのアクセスが許可されます。 212 モバイルアプリケーションでの認証、セキュリティ、ID ID URL の使用 メモ: Mobile SDK アプリケーションでは、サーバ側の [接続アプリケーション] 設定で常に refresh_token を選択する必要があります。範囲に full を選択しても、refresh_token を明示的に選択する必要があ ります。 クライアント側の設定 Mobile SDK アプリケーションの範囲の設定は、次のルールで制御されます。 範囲 Mobile SDK アプリケーションの設定 refresh_token アプリケーションの Mobile SDK から暗黙的に要求され ます。要求に含める必要はありません。 api Salesforce REST API コールを行う場合に、要求に含め ます (ほとんどのアプリケーションに適用されます)。 web Salesforce 組織で定義されたページにアプリケーション からアクセスする場合に、要求に含めます (Salesforce ベースの Web ページを読み込むハイブリッドアプリ ケーションおよびネイティブアプリケーションの場合)。 full すべての権限を要求する場合に含めます (Mobile SDK では、refresh_token が暗黙的に要求されます)。 chatter_api アプリケーションから Chatter REST API をコールする 場合に、要求に含めます。 id (不要) visualforce Web を代わりに使用します。 ID URL の使用 id パラメータでは、アクセストークンのほか、トークン応答の一部として ID URL も返されます。 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 である必要があります。 213 モバイルアプリケーションでの認証、セキュリティ、ID ID URL の使用 ID URL パラメータ 次のパラメータは、アクセストークンや ID URL と併用できます。アクセストークンは、認証要求ヘッダーや oauth_token パラメータのある要求で使用できます。 パラメータ 説明 Access token Salesforce ヘルプの 「アクセストークンの使用」を参照してください。 Format このパラメータは省略可能です。返される出力の形式を指定します。有効な 値は、次のとおりです。 • urlencoded • json • xml format パラメータを使用する代わりに、クライアントは次のいずれかを使用 して、受け入れ要求ヘッダーの返される形式も指定できます。 • • • Accept: application/json Accept: application/xml Accept: application/x-www-form-urlencoded 次の点に注意してください。 • • • ワイルドカードを受け入れるヘッダーが許可されます。*/* が受け入れら れ、JSON を返します。 値のリストも受け入れられ、左から右に確認されます。たとえば、 application/xml,application/json,application/html,*/* は XML を返します。 format パラメータは、受け入れ要求ヘッダーより優先されます。 version このパラメータは省略可能です。SOAP API バージョン番号またはリテラル 文字列 latest を指定します。この値が指定されていない場合、返される API URL に、クライアントが文字列置換を実行するためのバージョン番号の代わ りに、リテラル値 {version} が含まれます。値が latest として指定される と、最新の API バージョンが使用されます。 PrettyPrint このパラメータは省略可能で、ヘッダー内でのみ使用できます。URL パラ メータとしては使用できません。最適なフォーマットになるように出力を指 定します。たとえば、ヘッダーで X-PrettyPrint:1 を使用します。この値 が指定されない場合、返される XML または JSON は読みやすさではなくサ イズで最適化されます。 Callback このパラメータは省略可能です。有効な JavaScript 関数名を指定します。この パラメータは、形式が JSON として指定されている場合にのみ使用されます。 出力はこの関数名 (JSONP) でラップされます。たとえば、 https://server/id/orgid/userid/ に対する要求では {"foo":"bar"} を 返し、https://server/id/orgid/userid/?callback=baz に対する要求で は baz({"foo":"bar"}); を返します。 ID URL レスポンス 有効な要求を作成したら、インスタンス URL に 302 リダイレクト が返されます。後続の要求では、JSON 形式 で次の情報が返されます。 214 モバイルアプリケーションでの認証、セキュリティ、ID ID URL の使用 • 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)) を示します。Salesforce • ヘルプの 「ユーザの編集」を参照してください。 first_name — ユーザの名 • last_name — ユーザの姓 • timezone — ユーザの設定のタイムゾーン • photos — ユーザプロファイルの写真への URL の対応付け メモ: これらの URL にアクセスするには、アクセストークンを渡す必要があります。Salesforce ヘル プの 「アクセストークンの使用」を参照してください。 ◊ picture ◊ thumbnail • addr_street — ユーザの設定の住所で指定されている町名・番地 • addr_city — ユーザの設定の住所で指定されている市区郡 • addr_state — ユーザの設定の住所で指定されている都道府県 • addr_country — ユーザの設定の住所で指定されている国 • addr_zip — ユーザの設定の住所で指定されている郵便番号 • mobile_phone — ユーザの設定の携帯電話番号 • mobile_phone_verified — 有効な番号であることをユーザが確認した携帯電話番号。[モバイルユーザ] 項 • 目の説明を参照してください。 status — ユーザの現在の Chatter 状況 ◊ created_date: 2010-05-08T05:17:51.000Z など、ユーザの前回の投稿の作成日付の xsd datetime 値 ◊ body: 投稿の本文 • urls — 指定されたユーザで使用できる、さまざまな API エンドポイントを含む対応付け。 メモ: REST エンドポイントへのアクセスでは、アクセストークンを渡す必要があります。Salesforce ヘルプの 「アクセストークンの使用」を参照してください。 ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ enterprise (SOAP) metadata (SOAP) partner (SOAP) rest (REST) sobjects (REST) search (REST) query (REST) recent (REST) profile 215 モバイルアプリケーションでの認証、セキュリティ、ID ◊ ◊ ◊ ◊ ◊ ID URL の使用 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 — モバイルアプリケーションにアクセスするために必要な識別番号の長さ XML 形式のレスポンスは、次のとおりです。 <?xml version="1.0" encoding="UTF-8"?> <user xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <id>http://na1.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>http://na1.salesforce.com/profilephoto/005/F</picture> <thumbnail>http://na1.salesforce.com/profilephoto/005/T</thumbnail> </photos> <urls> <enterprise>http://na1.salesforce.com/services/Soap/c/{version}/00Dx0000001T0zk </enterprise> <metadata>http://na1.salesforce.com/services/Soap/m/{version}/00Dx0000001T0zk </metadata> <partner>http://na1.salesforce.com/services/Soap/u/{version}/00Dx0000001T0zk </partner> <rest>http://na1.salesforce.com/services/data/v{version}/ </rest> <sobjects>http://na1.salesforce.com/services/data/v{version}/sobjects/ </sobjects> <search>http://na1.salesforce.com/services/data/v{version}/search/ </search> <query>http://na1.salesforce.com/services/data/v{version}/query/ </query> <profile>http://na1.salesforce.com/005x0000001S2b9 </profile> 216 モバイルアプリケーションでの認証、セキュリティ、ID ID URL の使用 </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":"http://na1.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":"http://na1.salesforce.com/profilephoto/005/F", "thumbnail":"http://na1.salesforce.com/profilephoto/005/T"}, "urls": {"enterprise":"http://na1.salesforce.com/services/Soap/c/{version}/00Dx0000001T0zk", "metadata":"http://na1.salesforce.com/services/Soap/m/{version}/00Dx0000001T0zk", "partner":"http://na1.salesforce.com/services/Soap/u/{version}/00Dx0000001T0zk", "rest":"http://na1.salesforce.com/services/data/v{version}/", "sobjects":"http://na1.salesforce.com/services/data/v{version}/sobjects/", "search":"http://na1.salesforce.com/services/data/v{version}/search/", "query":"http://na1.salesforce.com/services/data/v{version}/query/", "profile":"http://na1.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 から次のレスポンスを受信する可能性があります。 要求の問題 エラーコード HTTP 403 (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 無効なバージョン 406 (not acceptable) — Invalid_Version 無効なコールバック 406 (not acceptable) — Invalid_Callback 217 モバイルアプリケーションでの認証、セキュリティ、ID カスタムログインサーバの設定 カスタムログインサーバの設定 Trialforce を使用する Salesforce パートナーなど、特殊な場合は、カスタムログイン要求を非標準のログイン URI にリダイレクトする必要がある場合があります。iOS アプリケーションでは、アプリケーションの iOS 設定バン ドルでカスタムホストを設定します。これが設定済みである場合は、デフォルトの接続として使用されます。 Android の設定 Android では、ログインホストはサーバ接続と呼ばれます。Mobile SDK バージョン 1.4 より前のバージョンで は、Android アプリケーションのサーバ接続が SalesforceSDK プロジェクトでハードコードされていました。バー ジョン 1.4 以降では、ホストのリストが res/xml/servers.xml ファイルで定義されています。SalesforceSDK ラ イブラリプロジェクトでは、このファイルを使用して本番サーバと Sandbox サーバを定義します。 アプリケーションプロジェクトで独自の res/xml/servers.xml ファイルを作成することで、サーバをランタイ ムリストに追加できます。このファイルのルート XML 要素は <servers> です。このルートには、<server> エ ントリをいくつでも含めることができます。各 <server> エントリには、name (わかりやすい任意のラベル) と url (ログインサーバの Web アドレス) という 2 つの属性が必要です。 servers.xml ファイルの例を次に示します。 <?xml version="1.0" encoding="utf-8"?> <servers> <server name="XYZ.com Login" url="https://<username>.cloudforce.com"/> </servers> サーバのホワイトリストエラー ホワイトリスト却下エラーが発生した場合は、カスタムログインドメインをプロジェクトの ExternalHosts リ ストに追加する必要があります。このリストは、<project_name>/<platform_path>/config.xml ファイルで 定義されます。ドメイン (cloudforce.com など) を、次のファイルのアプリケーションのホワイトリストに追加し ます。 Mobile SDK 2.0 の場合: • • iOS: /Supporting Files/config.xml Android: /res/xml/config.xml OAuth トークンの取り消し ユーザがアプリケーションからログアウトした、アプリケーションがタイムアウトした、または他の理由により 無効になった場合、ログインしたユーザのログイン情報はモバイルアプリケーションからクリアされます。これ により、サーバ接続が効果的に終了します。また、Mobile SDK では、ログアウトの一環としてサーバから更新 トークンも取り消されます。 トークンの取り消し OAuth 2.0 トークンを取り消すには、取り消しのエンドポイントを使用します。 https://login.salesforce.com/services/oauth2/revoke 218 モバイルアプリケーションでの認証、セキュリティ、ID Android ネイティブアプリケーションでの更新トークン の取り消し処理 HTTP 要求の entity-body に application/x-www-form-urlencoded 形式を使用して、次のパラメータを含む POST 要求を記述します。次に例を示します。 POST /revoke HTTP/1.1 Host: https://login.salesforce.com/services/oauth2/revoke Content-Type: application/x-www-form-urlencoded token=currenttoken アクセストークンが含まれる場合、それを無効化してトークンを取り消します。要求トークンが含まれる場合、 それを取り消して、すべての関連するアクセストークンを取り消します。 認証サーバは、HTTP ステータスコード 200 を返し、要求が正常に処理されたことを示します。すべてのエラー 条件については、ステータスコード 400 と次のいずれかのエラーレスポンスが使用されます。 • unsupported_token_type — サポートされていないトークンのタイプ • invalid_token — トークンが無効 Sandbox には、login.salesforce.com ではなく test.salesforce.com を使用してください。 Android ネイティブアプリケーションでの更新トークンの取り消し処理 Salesforce Mobile SDK バージョン 1.5 以降では、システム管理者が更新トークンを取り消したときの操作をネイ ティブ Android アプリケーションで制御できます。この場合のデフォルトの動作は、現在のユーザを自動的にロ グアウトすることです。その結果、次のようになります。 • アプリケーションで行う後続の REST API コールがすべて失敗する。 • ユーザのアカウント情報と、キャッシュされたオフラインデータが破棄される。 • ユーザがページから強制的に移動される。 • アプリケーションを引き続き使用するには、ユーザが Salesforce に再度ログインする必要がある。 副次的影響として、管理者のアクションに対して安全な応答が行われますが、必ずしもアプリケーションに適し ていない可能性もあります。デフォルトの動作を受け入れるか、独自の応答を実装するかを、コード内で選択で きます。いずれの場合も、以下のセクションを読み、コードを適合させる必要があるかどうかを判断してくださ い。 トークンの取り消しイベント トークンの取り消しイベントが発生すると、ClientManager オブジェクトから Android スタイルの通知が送信 されます。この通知が意図するアクションは、ClientManager.ACCESS_TOKEN_REVOKE_INTENT 定数で宣言さ れます。ユーティリティクラス TokenRevocationReceiver は、この意図するアクションに応答するよう設計さ れています。独自のハンドラを指定するには、このクラスを拡張し、onReceive() メソッドを上書きします。 「トークンの取り消し: アクティブ処理」を参照してください。 ACCESS_TOKEN_REVOKE_INTENT イベントリスナーは、SalesforceActivity.java、 SalesforceListActivity.java、SalesforceExpandableListActivity.java、および SalesforceDroidGapActivity.java で実装されます。更新トークンが取り消されると、これらのリスナーに よりユーザがログインページに自動的にログアウトされます。このことは、トーストメッセージによりユーザに 通知されます。 219 モバイルアプリケーションでの認証、セキュリティ、ID トークンの取り消し: パッシブ処理 トークンの取り消し: パッシブ処理 ユーザが何も操作を行わずに、トークンのすべての取り消しイベントを SDK で処理することができます。ただ し、このパッシブな方法を使用する場合でも、コードを変更する必要があります。次のいずれかの場合には、 コードを変更する必要はありません。 • • アプリケーションにサービスが含まれている すべてのアクティビティが SalesforceActivity、SalesforceListActivity、または SalesforceExpandableListActivity を拡張する 以上の少なくとも 1 つの条件がアプリケーションで満たされない場合は、次のコード変更を行います。 1. (Mobile SDK 1.5 リリースより前に作成された従来のアプリケーションの場合) ClientManager コンストラク タで、revokedTokenShouldLogout パラメータを true に設定します。 メモ: Mobile SDK 1.5 以降の新しいアプリケーションの場合は、この手順は不要です。 2. SalesforceActivity、SalesforceListActivity、または SalesforceExpandableListActivity を拡張 しないアクティビティで、コードを次のように修正します。 a. 新しい変数を宣言します。 private TokenRevocationReceiver tokenRevocationReceiver; b. onCreate() メソッドで、次のコードを追加します。 tokenRevocationReceiver = new TokenRevocationReceiver(this); c. onResume() メソッドで、次のコードを追加します。 registerReceiver(tokenRevocationReceiver, new IntentFilter(ClientManager.ACCESS_TOKEN_REVOKE_INTENT)); d. onPause() メソッドで、次のコードを追加します。 unregisterReceiver(tokenRevocationReceiver); トークンの取り消し: アクティブ処理 トークンの取り消しの独自のイベントハンドラを実装する場合は、カスタマイズしたフローがセキュリティに与 える影響を完全に分析してから、十分にテストしてください。特に、キャッシュされたユーザデータの処理方法 には注意してください。ユーザアクセスが取り消されるため、そのユーザは機密データにアクセスできなくなり ます。 トークンの取り消しイベントをカスタム処理する手順は、次のとおりです。 220 モバイルアプリケーションでの認証、セキュリティ、ID 接続アプリケーション 1. 独自の応答を実装するには、SalesforceSDKManager.shouldLogoutWhenTokenRevoked() メソッドから開 始します。デフォルトでは、このメソッドから true が返されます。SalesforceSDKManager サブクラスで、 false が返されるように、このメソッドを上書きします。 @Override public boolean shouldLogoutWhenTokenRevoked() { return false; } 2. ClientManager コンストラクタには、Boolean パラメータ revokedTokenShouldLogout があります。このパ ラメータを false に設定します。これを行うには、SalesforceSDKManager サブクラスで shouldLogoutWhenTokenRevoked() をコールします。 3. TokenRevocationReceiver を拡張し、onReceive() メソッドを上書きして、ハンドラを実装します。 4. アクティビティサブクラス SalesforceActivity に関係なく、「トークンの取り消し: パッシブ処理」のス テップ 2 を実行します。 接続アプリケーション 接続アプリケーションとは、API を使用して salesforce.com と統合するアプリケーションです。接続アプリケー ションでは、標準の SAML および OAuth プロトコルを使用して認証して、シングルサインオンを提供し、 Salesforce API を使用してトークンを提供します。標準の OAuth 機能に加え、接続アプリケーションでは、シス テム管理者はさまざまなセキュリティポリシーを設定したり、アプリケーションを使用できるユーザを明示的に 制御したりできます。 接続アプリケーションでは、開発者は最初に、次を含む、アプリケーションに関する OAuth メタデータを定義 します。 • 接続アプリケーションの基本的な説明情報および連絡先情報 • 接続アプリケーションの OAuth の範囲およびコールバック URL • 接続アプリケーションが実行されている可能性のある省略可能な IP 範囲 • 接続アプリケーションが適用できるモバイルポリシーに関する省略可能な情報 それらの定義と引き換えに、開発者には接続アプリケーションの OAuth クライアント ID およびクライアントの 秘密が提供されます。そのため、開発者は、アプリケーションをパッケージ化して、Salesforce システム管理者に 提供できます。 Salesforce Mobile SDK アプリケーションは、接続アプリケーションを使用して Salesforce OAuth サービスにアク セスし、Salesforce REST API をコールします。 PIN セキュリティについて Salesforce 接続アプリケーションには、アプリケーションでの PIN 保護を介した追加のセキュリティレイヤがあ ります。この PIN 保護はモバイルアプリケーションそれ自体用であり、Salesforce 組織が提供する、デバイスま たはログインセキュリティの PIN 保護とは異なります。 PIN 保護を使用するためには、開発者は接続アプリケーションの作成時に [画面ロックと固定保護を実装] チェッ クボックスをオンにする必要があります。オンにすることで、モバイルアプリケーション管理者は、PIN 保護の 強制実行、タイムアウト期間のカスタマイズ、PIN の長さの設定を行うかどうかを選択できます。 221 モバイルアプリケーションでの認証、セキュリティ、ID OAuth 2.0 サイトおよび Force.com サイトを使用したポー タル認証 メモ: PIN セキュリティはモバイルデバイスのオペレーティングシステムで実装されるため、ネイティブ およびハイブリッドのモバイルアプリケーションのみが PIN 保護を使用でき、HTML5 Web アプリケー ションは PIN 保護を使用できません。 PIN 保護は実際面では、モバイルアプリケーションが指定の時間 (分単位) 使用されていないかどうかを調べるた めに使用できます。モバイルアプリケーションがバックグラウンドに渡されても、経過時間は引き続き記録され ます。 PIN 保護の仕組みは、次のとおりです。 1. 電話を有効にし、デバイスの PIN を入力します。 2. モバイルアプリケーション (接続アプリケーション) を開始します。 3. Salesforce 組織のログイン情報を入力します。 4. モバイルアプリケーションの PIN コードを入力します。 5. アプリケーションで操作し、別のアプリケーションを開く (コールの受信など) ことによってアプリケーショ ンをバックグラウンドに送ります。 6. モバイルアプリケーションがタイムアウトになります。 7. アプリケーションを再び開き、アプリケーションの PIN 画面 (デバイス用ではなく、モバイルアプリケーショ ン用) が表示されます。 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 サイトの関連付け」 を参照してください。 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> 222 モバイルアプリケーションでの認証、セキュリティ、ID OAuth 2.0 サイトおよび Force.com サイトを使用したポー タル認証 次のように、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」を参 照してください。 223 第 14 章 Mobile SDK アプリケーションでの Communities の使用 トピック: • • • • • • • • • • コミュニティと Mobile SDK アプ リケーション 「API の有効化」プロファイルを 設定する 権限セットを設定する API アクセス権をユーザに付与す る ログインエンドポイントを設定す る コミュニティのブランド設定 コミュニティログインのカスタマ イズ コミュニティでの外部認証の使用 例: Mobile SDK アプリケーション からアクセスできるようにコミュ ニティを設定する 例: Facebook 認証できるようにコ ミュニティを設定する Salesforce Communities は、以前のリリースのポータル機能に置き換わ るソーシャルアグリゲーション機能です。Communities には、最大 500 万ユーザを含めることができ、アイデア、アンサーおよび Chatter ア ンサーを使用して知識を共有する論理ゾーンが備わっています。適切 に設定すれば、コミュニティユーザは、コミュニティログイン情報を 使用して、Mobile SDK アプリケーションにアクセスできます。 Communities では、Site.com を利用して、コミュニティサイトやログイ ン画面をブランド設定することもできます。 224 Mobile SDK アプリケーションでの Communities の使用 コミュニティと Mobile SDK アプリケーション コミュニティと 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 のヘルプの 「Salesforce コミュニティの有効化」を参照してください。ドメイン名を作成するように求められた場合、ドメイ ン名に SSL (https://) を使用しないでください。 コミュニティを設定する場合は、Salesforce のヘルプの「コミュニティの作成」を参照してください。コミュニ ティ機能を有効にしたときに作成したドメイン名に基づいて、コミュニティ URL を定義します。 次に、「API の有効化」権限のあるプロファイルを 1 つ以上設定します。これらのプロファイルを使用して、コ ミュニティメンバーの Mobile SDK アプリケーションを有効にできます。詳細は、「例: Mobile SDK アプリケー ションからアクセスできるようにコミュニティを設定する」のチュートリアルを参照してください。 1. 新しいプロファイルを作成するか、既存のプロファイルを編集します。 2. プロファイルを詳細を編集して、[システム管理者権限] の [API の有効化] を選択します。 3. 変更を保存してから、[設定] > [カスタマイズ] > [コミュニティ] > [コミュニティを管理する] でコミュニティ を編集します。 4. [<あなたのコミュニティ>: コミュニティ設定] で、[メンバー] をクリックします。 225 Mobile SDK アプリケーションでの Communities の使用 権限セットを設定する 5. 「API の有効化」プロファイルを [選択済みプロファイル] に追加します。 これで、これらのプロファイルが割り当てられているユーザに API アクセス権が付与されました。プロファイル の概要は、Salesforce ヘルプの「ユーザプロファイルの概要」を参照してください。 権限セットを設定する 権限セットを使用して、コミュニティのモバイルアプリケーションを有効にすることもできます。 1. 「API の有効化」権限を既存の権限セットに追加するには、[設定] で [ユーザの管理] > [権限セット] をクリッ クして権限セットを選択し、ステップ 6 に進みます。 2. 権限セットを作成するには、[設定] で [管理] > [ユーザの管理] > [権限セット] をクリックします。 3. [新規] をクリックします。 4. 権限セットに表示ラベルを指定して、Enter キーを押すと、自動的に API 名が作成されます。 5. [次へ] をクリックします。 6. [アプリケーション] セクションで、[アプリケーション権限] をクリックします。 7. [アプリケーション権限] をクリックして [システム] > [システム権限] を選択します。 226 Mobile SDK アプリケーションでの Communities の使用 API アクセス権をユーザに付与する 8. [システム権限] ページで [編集] をクリックして [API の有効化] を選択します。 9. [保存] をクリックします。 10. [設定] > [カスタマイズ] > [コミュニティ] > [コミュニティを管理する] に移動し、コミュニティ名の横にある [編集] をクリックします。 11. [私のコミュニティ: コミュニティ設定] で、[メンバー] をクリックします。 12. [権限セットを選択] で、「API の有効化」権限セットを [選択済みの権限セット] に追加します。 これで、この権限セットのユーザに API アクセス権が付与されました。 API アクセス権をユーザに付与する API アクセス権をコミュニティユーザに拡張するには、「API の有効化」権限を設定するプロファイルまたは権 限セットにコミュニティユーザを追加します。この権限を含むプロファイルまたは権限セットをまだ設定してい ない場合は、「「API の有効化」プロファイルを設定する」および「権限セットを設定する」を参照してくださ い。 ログインエンドポイントを設定する 最後に、コミュニティログインエンドポイントを使用するようにアプリケーションを設定します。アプリケー ションのモバイルプラットフォームにより、この設定方法が決まります。 227 Mobile SDK アプリケーションでの Communities の使用 コミュニティのブランド設定 Android Android では、ログインホストはサーバ接続と呼ばれます。Mobile SDK バージョン 1.4 より前のバージョンで は、Android アプリケーションのサーバ接続が SalesforceSDK プロジェクトでハードコードされていました。バー ジョン 1.4 以降では、ホストのリストが res/xml/servers.xml ファイルで定義されています。SalesforceSDK ラ イブラリプロジェクトでは、このファイルを使用して本番サーバと Sandbox サーバを定義します。アプリケー ションプロジェクトで独自の res/xml/servers.xml ファイルを作成することで、サーバをランタイムリストに 追加できます。このファイルのルート XML 要素は <servers> です。このルートには、<server> エントリをい くつでも含めることができます。各 <server> エントリには、name (わかりやすい任意のラベル) と url (ログイ ンサーバの Web アドレス) という 2 つの属性が必要です。 次に例を示します。 <?xml version="1.0" encoding="utf-8"?> <servers> <server name="XYZ.com Login" url="https://<username>.cloudforce.com"/> </servers> iOS iOS アプリケーションでは、アプリケーションの iOS 設定バンドルでカスタムホストを設定します。これが設定 済みである場合は、デフォルトの接続として使用されます。次のキー - 値のペアを <アプリケーション名>-Info.plist ファイルに追加します。 <key>SFDCOAuthLoginHost</key> <string>your_community_login_url_minus_the_https://_prefix</string> URL から HTTP プレフィックスを削除することが重要です。たとえば、コミュニティログイン URL が https://mycommunity-developer-edition.na15.force.com/fineapps の場合、キー - 値のペアは次のよう になります。 <key>SFDCOAuthLoginHost</key> <string>mycommunity-developer-edition.na15.force.com/fineapps</string> ユーザがこの値を変更できないようにする場合、必要に応じてクラスから Settings.bundle を削除できます。 コミュニティのブランド設定 使用可能なエディション: Enterprise Edition、Performance Edition、Unlimited Edition、および Developer Edition 必要なユーザ権限 コミュニティを作成、カスタマイズ、公開する 「コミュニティの作成および管理」 会社のロゴ、色、著作権表示を追加して、コミュニティのデザインをカスタマイズします。これにより、コミュ ニティが会社のブランド設定と一致し、コミュニティメンバーがただちに認識できるようになります。 1. [設定] から、[カスタマイズ] > [コミュニティ] > [コミュニティを管理する] をクリックし、コミュニティ名の 横にある [編集] をクリックします。 2. [ブランド] をクリックします。 228 Mobile SDK アプリケーションでの Communities の使用 コミュニティログインのカスタマイズ 3. ルックアップを使用して、コミュニティのヘッダーとフッターを選択します。 ヘッダーとフッター用に選択するファイルは、[ドキュメント] タブにアップロード済みで、公開されている 必要があります。ヘッダーには、.html、.gif、.jpg、または .png を使用できます。フッターは、.html ファイル である必要があります。.html ファイルの合計最大サイズは 100 KB です。.gif、.jpg、または .png ファイルの 最大サイズは 20 KB です。このため、ヘッダーの .html ファイルが 70 KB で、.html ファイルをフッターにも 使用する場合は、30 KB 以内にする必要があります。 選択したヘッダーは、グローバルヘッダーの下にある Salesforce ロゴに置き換わります。選択したフッター は、Salesforce 標準の著作権とプライバシーのフッターに置き換わります。 4. [配色を選択] をクリックして事前定義された配色を選択するか、ページ選択項目の横にあるテキストボック スをクリックしてカラーピッカーから色を選択します。 選択した色の中には、コミュニティのログインページや Salesforce1 のコミュニティの外観にも影響を与える ものもあります。 色の選択肢 表示場所 ヘッダー背景 黒のグローバルヘッダーの下のページ上部。[ヘッダー] 項目で HTML ファイルを選択 した場合は、この色が上書きされます。 ログインページ上部。 ページ背景 ログインページを含む、コミュニティのすべてのページの背景色。 プライマリ 選択されたタブ。 セカンダリ リストとテーブルの上境界線。 ログインページのボタン。 ターティアリ 編集と詳細ページのセクションヘッダーの背景色。 5. [保存] をクリックします。 コミュニティログインのカスタマイズ ロゴおよびフッターから外部ユーザのログインオプションにいたるまでの、コミュニティのログインページのデ ザインをカスタマイズします。 使用可能なエディション: Enterprise Edition、Performance Edition、Unlimited Edition、および Developer Edition 必要なユーザ権限 コミュニティを作成、カスタマイズ、公開する 「コミュニティの作成および管理」 ログインページで使用する色は、コミュニティのブランド設定の配色から継承されます。ページのその他の要素 もカスタマイズできます。 1. [設定] から、[カスタマイズ] > [コミュニティ] > [コミュニティを管理する] をクリックし、コミュニティ名の 横にある [編集] をクリックします。 229 Mobile SDK アプリケーションでの Communities の使用 コミュニティログインのカスタマイズ 2. [ログインページ] をクリックします。 3. コミュニティのログインページヘッダーのロゴをアップロードします。 ファイルには、.gif、.jpg、または .png を使用できます。最大ファイルサイズは 100 KB です。幅が 250 ピクセ ル、高さが 125 ピクセルを超える画像は無効です。ロゴをアップロードすると、[ドキュメント] タブにコミュ ニティで共有するドキュメントフォルダが自動的に作成され、ロゴがそこに保存されます。一度作成された フォルダは、削除できません。 ヘッダーのロゴは、ログインページの左上に表示されます。これは、Salesforce1 でコミュニティにアクセスす る場合にも使用されます。 4. コミュニティのログインページフッターに、カスタムテキストを 120 文字以内で入力します。 フッターは、ログインページ下部に表示されます。 5. コミュニティのログインページで外部ユーザに提供するログインオプションを選択します。 外部ユーザとは、コミュニティのユーザ、カスタマーポータルまたはパートナーポータルライセンスを持つ ユーザです。 外部ユーザのログインオプション ログインページの表示内容 組織名 にログインするためのユーザ名とパスワード コミュニティのユーザに対して 割り当てられたユーザ名とパス ワードを使用してログインする ためのオプション。これは、デ フォルトのログインオプション です。 シングルサインオン用の SAML ユーザの SAML シングルサイン オン ID を使用して [シングルサ このオプションは、組織で次の 2 つを正常に設定した場合にのみ使用でき インオンでログイン] を行うため ます。 のオプション。 • 企業 ID プロバイダを使用して Salesforce にログインできるようにする、 複数の SAML シングルサインオ シングルサインオン用の SAML 設定。ID プロバイダのログイン URL ンオプションを有効化した場合 を入力する必要があります。 は、各ログインボタンに SAML • ログインページを含むすべてのページのアプリケーション URL を変更 設定の [名前] 項目でラベル付け する、カスタム Salesforce ドメイン名。[私のドメイン] を有効化する必 されて表示されます。 要がある場合は、サポートにお問い合わせください。 [設定] の [セキュリティのコントロール] > [シングルサインオン設定] で [複 数の設定を有効化] を行う場合は、複数の SAML シングルサインオンオプ ションをユーザに提供できます。SAML をすでに有効化した場合に、複数 の SAML 設定を有効化すると、複数の追加設定で動作するように既存の SAML 設定が自動的に変換されます。 外部認証プロバイダ Facebook©、Janrain©、または Salesforce などの外部サービスプ これらのオプションは、[設定] の [セキュリティのコントロール] > [認証プ ロバイダのログイン情報を使用 ロバイダ] で有効化されている場合に使用できます。 してログインするためのオプ ション。 230 Mobile SDK アプリケーションでの Communities の使用 コミュニティでの外部認証の使用 外部ユーザのログインオプション ログインページの表示内容 セルフ登録 外部ユーザをセルフ登録ページ に移動する [メンバーではありま コミュニティのシステム管理者のみに依存してメンバーを追加するのでは せんか?] リンク。 なく、[外部ユーザにセルフ登録を許可] を使用してデフォルトプロファイル を選択できます。このプロファイルは、セルフ登録するユーザに割り当て られます。 メモ: コミュニティに関連付けられているポータルプロファイルし か選択できません。 プロファイルがセルフ登録するユーザのデフォルトとして選択され ている場合に、そのプロファイルをコミュニティから削除すると、 [セルフ登録するユーザのデフォルトプロファイル] が自動的に [なし] にリセットされます。 最初のコミュニティを作成すると、セルフ登録 Visualforce ページおよび関 連する Apex コントローラのデフォルトのセットが作成されます。デフォ ルトのコントローラで、セルフ登録プロセスでユーザに割り当てるアカウ ントを指定する必要があります。プロファイルを指定することもできます が、セルフ登録を有効にするときに選択されるデフォルトが上書きされま す。セルフ登録機能は、これらの詳細を指定するまで動作しません。 メモ: ユーザがセルフ登録するたびに、1 つのコミュニティライセ ンスが使用されます。セルフ登録ページの設定時には、条件を追加 して適切なユーザがサインアップするようにしてください。また、 未承認のフォーム登録を回避するため、セルフ登録ページで CAPTCHA や非表示項目などのセキュリティメカニズムを使用す ることをお勧めします。 6. [保存] をクリックします。 選択したログインオプションが、ログインページですべてのユーザに表示されます。ただし、これらのオプショ ンは外部ユーザに対してのみ有効です。内部ユーザがこれらのオプションを使用しようとすると、ログインエ ラーになります。内部ユーザは、従業員を [こちらにログイン] に移動するリンクを使用し、Salesforce ユーザ名 とパスワードでログインする必要があります。 コミュニティでの外部認証の使用 Facebook© などの外部認証プロバイダを使用して、コミュニティユーザを Mobile SDK アプリケーションにログ インさせることができます。 メモ: Salesforce では、Janrain を認証プロバイダとして使用できますが、これは基本的に Salesforce で内部 的に使用することを目的としています。ここで Janrain を説明した理由は、すべての情報を網羅するため です。 231 Mobile SDK アプリケーションでの Communities の使用 外部認証プロバイダについて 外部認証プロバイダについて 必要なユーザ権限 設定を参照する 「設定・定義を参照する」 設定を編集する 「アプリケーションのカスタマイズ」 および 「認証プロバイダの管理」 Facebook©、Janrain©などの外部サービスプロバイダのログイン情報を使用して、Salesforce 組織にユーザがログ インできるようにできます。シングルサインオン用認証プロバイダを正常に設定するには、次を実行する必要が あります。 • サービスプロバイダの Web サイトを正しく設定する。 • Apex を使用して登録ハンドラを作成する。 • 組織の認証プロバイダを定義する。 メモ: プロファイルにログイン IP 範囲制限が含まれるユーザ、またはセッションロックを使用する組織 は、認証プロバイダを使用できません。 認証プロバイダの設定後の基本フローは次のとおりです。 1. ユーザがサードパーティ ID を使用して Salesforce にログインしようとします。 2. ログイン要求はサードパーティの認証プロバイダにリダイレクトされます。 3. ユーザはサードパーティログインを実行して、アクセスを承認します。 4. 認証プロバイダは認証情報と共にユーザを Salesforce にリダイレクトします。 5. ユーザは Salesforce にサインインされます。 メモ: ユーザが既存の Salesforce セッションを持つ場合、サードパーティでの認証後、Salesforce アカウン トへのリンクを承認できるページに自動的にリダイレクトされます。 認証プロバイダの定義 次のプロバイダをサポートしています。 • • • • Facebook Janrain Salesforce OpenID Connect プロトコルを実装しているサービスプロバイダ 認証プロバイダへの機能の追加 追加の要求パラメータを使用して、認証プロバイダに機能を追加できます。 • • • Scope – サードパーティから要求された権限をカスタマイズする Site – プロバイダをサイトで使用可能にする StartURL – 認証後にユーザを指定された場所に送信する 232 Mobile SDK アプリケーションでの Communities の使用 コミュニティ URL パラメータの使用 Community – 認証後にユーザを特定のコミュニティに送信する • Apex 登録ハンドラの作成 登録ハンドラクラスはシングルサインオンフロー用の認証プロバイダを使用する必要があります。Apex 登録ハ ンドラクラスでは Auth.RegistrationHandler インターフェースを実装する必要があります。このインター フェースでは 2 つのメソッドを定義します。Salesforce では、ユーザがこのプロバイダを以前使用したかどうかに 応じて、コールバックで適切なメソッドを起動します。認証プロバイダを作成する場合、テストのために Apex テンプレートクラスを自動的に作成できます。 コミュニティ URL パラメータの使用 認証後に、ユーザを特定のコミュニティに送信します。 使用可能なエディション: 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 Scope パラメータの使用 返されたアクセストークンが追加権限を持つように、Facebook や Janrain などのサードパーティから要求された 権限をカスタマイズします。 使用可能なエディション: Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、お よび Developer Edition 233 Mobile SDK アプリケーションでの Communities の使用 Scope パラメータの使用 必要なユーザ権限 設定を参照する 「設定・定義を参照する」 設定を編集する 「アプリケーションのカスタマイズ」 および 「認証プロバイダの管理」 サードパーティへの要求をカスタマイズして、追加権限を持つアクセストークンを受け取ることができます。そ の後、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 の範囲は次のようになります。 値 説明 api REST API や Bulk API などの API を使用して、現在のログインユーザの取引先へ のアクセスを許可します。この値には、Chatter REST API リソースへのアクセスを 許可する chatter_api も含まれます。 chatter_api Chatter REST API リソースへのアクセスのみを許可します。 full ログインユーザがアクセスできるすべてのデータへのアクセスを許可します。full は更新トークンを返しません。更新トークンを取得するには、refresh_token の 範囲を明示的に要求する必要があります。 id ID URL サービスへのアクセスを許可します。profile、email、address、phone を要求すれば、id を使用した場合と同じ結果を個別に得られます。これらの結果 はすべて一致します。 234 Mobile SDK アプリケーションでの Communities の使用 Facebook 認証プロバイダの設定 値 説明 openid OpenID Connect アプリケーションの現在のログインユーザの一意の識別子へのア クセスを許可します。 アクセストークンの他にも、「OpenID Connect の仕様」に従って、OAuth 2.0 ユー ザエージェントフローおよび OAuth 2.0 Web サーバ認証フローで openid 範囲を使 用して、署名付き ID トークンを再度取得できます。 refresh_token 更新トークンを受信できる場合に、それを返すように指定します。これにより、 ユーザがオフラインのときにアプリケーションがユーザのデータを操作できます。 これは、offline_access を要求した場合と同じ意味になります。 visualforce Visualforce ページへのアクセスを許可します。 web Web で access_token を使用することを許可します。これには visualforce も含 まれ、Visualforce ページへのアクセスが許可されます。 Facebook 認証プロバイダの設定 必要なユーザ権限 設定を参照する 「設定・定義を参照する」 設定を編集する 「アプリケーションのカスタマイズ」 および 「認証プロバイダの管理」 Facebook を認証プロバイダとして使用する手順は、次のとおりです。 1. Facebook アプリケーションを設定し、Salesforce をアプリケーションのドメインにします。 2. Salesforce 組織の Facebook 認証プロバイダを定義します。 3. Salesforce によって生成される [コールバック URL] を Facebook の [Web サイトの URL] として使用するよう に、Facebook アプリケーションを更新します。 4. 接続をテストします。 Facebook アプリケーションの設定 Salesforce 組織で Facebook を設定するには、次の手順で Facebook でアプリケーションを設定する必要がありま す。 1. Facebook の Web サイトに移動して、新しいアプリケーションを作成します。 2. アプリケーション設定を変更し、アプリケーションドメインを Salesforce に設定します。 3. アプリケーション ID とアプリケーションシークレットを確認します。 Salesforce 組織での Facebook プロバイダの定義 Salesforce 組織で Facebook プロバイダを設定するには Facebook のアプリケーション ID とアプリケーションシー クレットが必要です。 235 Mobile SDK アプリケーションでの Communities の使用 Facebook 認証プロバイダの設定 1. [設定] で、[セキュリティのコントロール] > [認証プロバイダ] をクリックします。 2. [新規] をクリックします。 3. [プロバイダタイプ] には Facebook を選択します。 4. プロバイダの [名前] を入力します。 5. [URL 接尾辞] を入力します。これは、クライアント設定 URL で使用されます。たとえば、プロバイダの URL サフィックスが「MyFacebookProvider」である場合、シングルサインオン URL は https://login.salesforce.com/auth/sso/00Dx00000000001/MyFacebookProvider のようになります。 6. [コンシューマ鍵] 項目には、Facebook のアプリケーション ID を使用します。 7. [コンシューマの秘密] 項目には、Facebook のアプリケーションシークレットを使用します。 8. 必要に応じて、次の項目を設定します。 a. 認証エンドポイントへの要求と共に送信する [デフォルトの範囲]。送信しない場合は、プロバイダタイプ のハードコード化されたデフォルトが使用されます (デフォルトについてはFacebook’s の開発者向けドキュ メントを参照)。 詳細は、「Scope パラメータの使用」を参照してください。 b. エラーのレポートに使用するプロバイダの [カスタムエラー URL]。 c. 既存の Apex クラスを [登録ハンドラ] クラスとして選択するか、[登録ハンドラテンプレートを自動作成] を クリックして、登録ハンドラの Apex クラステンプレートを作成します。このクラスを編集してデフォル トのコンテンツを変更してから使用する必要があります。 メモ: Salesforce の登録ハンドラクラスを指定して、[シングルサインオン初期化 URL] を生成する必 要があります。 d. [他のアカウントで登録を実行] で Apex ハンドラクラスを実行するユーザを選択します。このユーザは 「ユーザの管理」権限を持っている必要があります。登録ハンドラを選択した場合、または登録ハンドラ を自動作成する場合にはユーザが必要です。 e. プロバイダでポータルを使用するには、[ポータル] ドロップダウンリストからポータルを選択します。 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 の認証を受ける必要があります。こ のフローでは、以降のシングルサインオン機能は提供されません。 236 Mobile SDK アプリケーションでの Communities の使用 • Salesforce 認証プロバイダの設定 コールバック URL: 認証プロバイダが設定のためにコールバックするエンドポイントに、コールバック URL を使用します。認証プロバイダは、前述の各クライアント設定 URL の情報と共に、[コールバック URL] にリ ダイレクトする必要があります。 クライアント設定 URL では、ユーザの特定サイトへのログイン、サードパーティからのカスタマイズされた権 限の取得、認証後の特定の場所への移動を行うための、追加の要求パラメータをサポートしています。 Facebook アプリケーションの更新 Facebook 認証プロバイダを Salesforce 組織に定義したら、Facebook に戻り、[コールバック URL] を Facebook の [Web サイトの URL] として使用するようにアプリケーションを更新します。 シングルサインオン接続のテスト ブラウザの認証プロバイダの詳細ページで [テスト専用初期化 URL] を開きます。このページによりユーザは Facebook にリダイレクトされ、サインインするよう求められます。サインイン時に、アプリケーションを認証す る求められます。認証後、ユーザは Salesforce にリダイレクトされます。 Salesforce 認証プロバイダの設定 必要なユーザ権限 設定を参照する 「設定・定義を参照する」 設定を編集する 「アプリケーションのカスタマイズ」 および 「認証プロバイダの管理」 リモートアクセスアプリケーションを認証プロバイダとして使用できます。次の手順を実行します。 1. リモートアクセスアプリケーションを定義します。 2. 組織の Salesforce 認証プロバイダを定義します。 3. 接続をテストします。 リモートアクセスアプリケーションの定義 Salesforce 組織の Salesforce プロバイダを設定するには、シングルサインオンを使用して、リモートアクセスアプ リケーションを定義する必要があります。[設定] の [作成] > [アプリケーション] で、新しい接続アプリケーショ ンとしてリモートアクセスアプリケーションを定義します。 リモートアクセスアプリケーションの定義の完了後は、[コンシューマ鍵] 項目および [コンシューマの秘密] 項目 の値を保存します。 組織の Salesforce 認証プロバイダの定義 リモートアクセスアプリケーション定義の [コンシューマ鍵] 項目および [コンシューマの秘密] 項目の値で組織の 認証プロバイダを設定する必要があります。 1. [設定] で、[セキュリティのコントロール] > [認証プロバイダ] をクリックします。 2. [新規] をクリックします。 237 Mobile SDK アプリケーションでの Communities の使用 Salesforce 認証プロバイダの設定 3. [プロバイダタイプ] には Salesforce を選択します。 4. プロバイダの [名前] を入力します。 5. [URL 接尾辞] を入力します。これは、クライアント設定 URL で使用されます。たとえば、プロバイダの URL サフィックスが「MySFDCProvider」である場合、シングルサインオン URL は https://login.salesforce.com/auth/sso/00Dx00000000001/MySFDCProvider のようになります。 6. リモートアクセスアプリケーション定義の [コンシューマ鍵] の値を [コンシューマ鍵] 項目に貼り付けます。 7. リモートアクセスアプリケーション定義の [コンシューマの秘密] の値を [コンシューマの秘密] 項目に貼り付 けます。 8. 必要に応じて、次の項目を設定します。 a. OAuth 認証の URL を指定するための [承認エンドポイント URL]。 [承認エンドポイント URL] の場合、ホスト名に Sandbox やカスタムドメイン名 ([私のドメイン] を使用して 作成) を含めることができますが、URL は .salesforce.com で終わり、パスは /services/oauth2/authorize で終わる必要があります。たとえば、 https://test.salesforce.com/services/oauth2/authorize などです。 b. OAuth トークンの URL を指定するための [トークンエンドポイント URL]。 [トークンエンドポイント URL] の場合、ホスト名に Sandbox やカスタムドメイン名 ([私のドメイン] を使用 して作成) を含めることができますが、URL は .salesforce.com で終わり、パスは /services/oauth2/token で終わる必要があります。たとえば、 https://test.salesforce.com/services/oauth2/token などです。 c. 認証エンドポイントへの要求と共に送信する [デフォルトの範囲]。送信しない場合は、ハードコード化さ れたデフォルトが使用されます。 詳細は、「Scope パラメータの使用」を参照してください。 d. エラーのレポートに使用するプロバイダの [カスタムエラー URL]。 9. 既存の Apex クラスを [登録ハンドラ] クラスとして選択するか、[登録ハンドラテンプレートを自動作成] をク リックして、登録ハンドラの Apex クラスを作成します。このテンプレートクラスを使用する前に、編集して デフォルトのコンテンツを変更する必要があります。 メモ: Salesforce の登録ハンドラクラスを指定して、[シングルサインオン初期化 URL] を生成する必要 があります。 10. [他のアカウントで登録を実行] で Apex ハンドラクラスを実行するユーザを選択します。このユーザは「ユー ザの管理」権限を持っている必要があります。登録ハンドラを選択した場合、または登録ハンドラを自動作 成する場合にはユーザが必要です。 11. プロバイダでポータルを使用するには、[ポータル] ドロップダウンリストからポータルを選択します。 12. [保存] をクリックします。 クライアント設定 URL の値を確認します。最後のステップを完了するには [コールバック URL] が必要です。 また、[テスト専用初期化 URL] を使用して、設定をチェックします。Auth.AuthToken Apex クラスと共に [認 証プロバイダ ID] 値を使用する必要があるため、その値を確認しておく必要もあります。 13. 前のステップで作成したリモートアクセスアプリケーション定義に戻り、認証プロバイダの [コールバック URL] の値を [コールバック URL] 項目に貼り付けます。 認証プロバイダを定義した後、複数のクライアント設定 URL が生成されます。 238 Mobile SDK アプリケーションでの Communities の使用 • OpenID Connect 認証プロバイダの設定 テスト専用初期化 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] を開きます。認証する側の組織および認証さ れる側の組織の両方が、本番または Sandbox など、同じ環境内にある必要があります。 OpenID Connect 認証プロバイダの設定 Amazon、Google、PayPal など、OpenID Connect プロトコルのサーバ側を実装するサードパーティの Web アプ リケーションを認証プロバイダとして使用できます。 必要なユーザ権限 設定を参照する 「設定・定義を参照する」 設定を編集する 「アプリケーションのカスタマイズ」 および 「認証プロバイダの管理」 OpenID 認証プロバイダを設定するには、次の手順を実行します。 1. アプリケーションを登録して、Salesforce をアプリケーションドメインにします。 2. Salesforce 組織の OpenID Connect 認証プロバイダを定義します。 3. Salesforce によって生成される [コールバック URL] をコールバック URL として使用するように、アプリケー ションを更新します。 4. 接続をテストします。 239 Mobile SDK アプリケーションでの Communities の使用 OpenID Connect 認証プロバイダの設定 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 は 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 形式で指定します。 c. 認証エンドポイントへの要求と共に送信する [デフォルトの範囲]。送信しない場合は、プロバイダタイプ のハードコード化されたデフォルトが使用されます (デフォルトについてはOpenID Connect の開発者用ド キュメントを参照)。 詳細は、「Scope パラメータの使用」 を参照してください。 240 Mobile SDK アプリケーションでの Communities の使用 OpenID Connect 認証プロバイダの設定 11. [ヘッダーでアクセストークンを送信] を選択すると、トークンをクエリ文字列ではなくヘッダーに送信できま す。 12. 必要に応じて、次の項目を設定します。 a. エラーのレポートに使用するプロバイダの [カスタムエラー URL]。 b. 既存の Apex クラスを [登録ハンドラ] クラスとして選択するか、[登録ハンドラテンプレートを自動作成] を クリックして、登録ハンドラの Apex クラステンプレートを作成します。このクラスを編集してデフォル トのコンテンツを変更してから使用する必要があります。 メモ: Salesforce の登録ハンドラクラスを指定して、[シングルサインオン初期化 URL] を生成する必 要があります。 c. [他のアカウントで登録を実行] で Apex ハンドラクラスを実行するユーザを選択します。このユーザは 「ユーザの管理」権限を持っている必要があります。登録ハンドラを選択した場合、または登録ハンドラ を自動作成する場合にはユーザが必要です。 d. プロバイダでポータルを使用するには、[ポータル] ドロップダウンリストからポータルを選択します。 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] とも呼ばれる) を更新します。 241 Mobile SDK アプリケーションでの Communities の使用 例: Mobile SDK アプリケーションからアクセスできるよ うにコミュニティを設定する シングルサインオン接続のテスト ブラウザの認証プロバイダの詳細ページで [テスト専用初期化 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 を有効化] を選択します。 メモ: 「Chatter の有効化」権限がないユーザは、Salesforce のコミュニティに正常にログインした直後 に「アクセス権がありません」エラーが表示されます。 8. [保存] をクリックします。 242 Mobile SDK アプリケーションでの Communities の使用 コミュニティを作成する メモ: このチュートリアルではプロファイルを使用しますが、必要な権限がある権限セットを使用するこ ともできます。 コミュニティを作成する コミュニティおよびコミュニティログイン 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. 確認ダイアログボックスを閉じて、[閉じる] をクリックします。 新しい取引先責任者およびユーザを作成する ユーザを直接作成する代わりに、取引先の取引先責任者を作成した後でその取引先責任者からユーザを作成しま す。 現在、取引先がない場合、次の手順を実行します。 1. [取引先] タブをクリックします。 243 Mobile SDK アプリケーションでの Communities の使用 新しいコミュニティログインをテストする 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」に設定します。 新しいコミュニティログインをテストする 新しい取引先責任者として Mobile SDK ネイティブまたはハイブリッドローカルアプリケーションにログインし、 コミュニティ設定をテストします。 コミュニティを介してモバイルアプリケーションにログインするには、/fineapps で終わるコミュニティログイ ン URL を識別するように Mobile SDK アプリケーションの設定を指定します。 1. Android の場合: a. Eclipse で Android プロジェクトを開きます。 b. プロジェクトエクスプローラで、res フォルダに移動し、新しい xml フォルダを作成するか、既存のフォ ルダを選択します。 c. xml フォルダで、新しいテキストファイルを作成します。これは、[ファイル] メニューまたは Ctrl-ク リック (または右クリック) メニューを使用して行うことができます。 244 Mobile SDK アプリケーションでの Communities の使用 例: Facebook 認証できるようにコミュニティを設定する 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. Xcode で iOS プロジェクトを開きます。 b. プロジェクトナビゲータで、[Supporting Files (補助ファイル)] > [<appname>-Info.plist] を開きます。 c. [SFDCOAuthLoginHost] の値を https:// プレフィックスを除いたコミュニティログイン URL に変更し ます。次に例を示します。 fineapps-developer-edition.<instance>.force.com/fineapps d. iOS シミュレータまたはデバイスで、[設定] > [<your_app_name>] に移動します。 e. [Login Host (ログインホスト)] をクリックして [Custom Host (カスタムホスト)] を選択します。 f. [戻る] をクリックします。 g. [Custom Host (カスタムホスト)] を編集し、<appname>-Info.plist ファイルで指定した SFDCOAuthLoginHost の値に設定します。 3. デバイス、シミュレータ、またはエミュレータでアプリケーションを起動し、ユーザ名 [email protected]、パスワード mobiletest1234 でログインします。 メモ: ログイン画面で長期間ログインせずにモバイルアプリケーションから離れていると、ログインしよ うとしたときに「アクセス権がありません」エラーが発生する可能性があります。この場合、アプリケー ションを閉じてから再度開き、すぐにログインします。 例: Facebook 認証できるようにコミュニティを設定する コミュニティログインを処理するように外部認証プロバイダを設定して、コミュニティへのアクセスを拡張でき ます。 この例では、Facebook を認証フロントエンドとして使用するように前の例を拡張します。この簡単なシナリオで は、認証された Facebook ユーザのコミュニティへの参加を許可できるように外部認証プロバイダを設定します。 モバイルアプリケーションにログインできるようにコミュニティがすでに設定されている場合、外部認証を使用 するようにモバイルアプリケーションまたは接続アプリケーションを変更する必要はありません。代わりに、 Facebook アプリケーション、Salesforce 認証プロバイダ、および認証プロバイダ Apex クラスを定義します。ま た、コミュニティの設定も若干変更します。 Facebook アプリケーションを作成する Facebook を介したコミュニティログインを有効にするには、まず Facebook アプリケーションを作成します。 245 Mobile SDK アプリケーションでの Communities の使用 Salesforce 認証プロバイダを定義する Facebook アプリケーションは、Salesforce 接続アプリケーションに相当します。接続アプリケーションは、モバ イルデバイスのアプリケーションの接続および認証を管理する設定用コンテナです。 1. developers.facebook.com に移動します。 2. Facebook 開発者アカウントでログインします。Facebook 開発者として登録していない場合は、登録します。 3. [アプリケーション] > [新規アプリケーションを作成] に移動します。 4. 表示名を「FineApps Community Test」(FineApps コミュニティテスト) に設定します。 5. 必要に応じて、名前空間を追加します。Facebook の要件に従って、小文字、ダッシュ、およびアンダースコ アのみで 12 文字以下の名前空間表示ラベルを入力する必要があります。たとえば、「my_fb_goodapps」のよ うになります。 6. [カテゴリ] で、[公益事業] を選択します。 7. 後で使用するためにアプリ ID とアプリのシークレットキーをコピーして保存します。 次の URL を使用してアプリケーションにログインできます。 https://developers.facebook.com/apps/<App ID>/dashboard/ Salesforce 認証プロバイダを定義する Salesforce で外部認証を有効にするには、認証プロバイダを作成します。 Facebook を介した外部認証には、前のステップで作成した Facebook アプリケーションのアプリケーション ID と アプリケーションのシークレットキーが必要です。 1. [設定] で [セキュリティのコントロール] > [認証プロバイダ] にアクセスします。 2. [新規] をクリックします。 3. 次の表に示すように、認証プロバイダの項目を設定します。 項目 値 プロバイダタイプ [Facebook] を選択します。 名前 「FB Community Login」(FB コミュニティログイ ン) と入力します。 URL 接尾辞 デフォルトを受け入れます。 メモ: URL 構文に適合するその他の文字列を 入力することもできますが、この例ではデフォ ルトが最適です。 コンシューマ鍵 Facebook アプリケーションのアプリケーション ID を 入力します。 コンシューマの秘密 Facebook アプリケーションのアプリのシークレット キーを入力します。 カスタムエラー URL 空白のままにします。 4. [登録ハンドラ] で、[登録ハンドラテンプレートを自動作成] をクリックします。 246 Mobile SDK アプリケーションでの Communities の使用 5. [他のアカウントで登録を実行] で、[検索] ます。 Facebook アプリケーションを設定する をクリックし、管理権限のあるコミュニティメンバーを選択し 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 アプリケーションで、[設定] に移動します。 2. [App Domains (アプリのドメイン)] に、「login.salesforce.com」と入力します。 3. [+プラットフォームを追加] をクリックします。 4. [Web サイト] を選択します。 5. [サイト URL] に、認証プロバイダのコールバック URL を入力します。 6. [連絡先メールアドレス] に、有効なメールアドレスを入力します。 7. 左側のパネルで、[Status & Review (ステータス & レビュー)] を [はい] に設定します。この設定により、すべ ての Facebook ユーザは Facebook ログインを使用して、コミュニティのユーザアカウントを作成できます。 8. [保存] をクリックします。 9. [確認] をクリックします。 認証プロバイダの Apex クラスをカスタマイズする 認証プロバイダの Apex クラスを使用して、コミュニティに参加できるユーザを制御する条件ロジックを定義し ます。 1. [設定] で [開発] > [Apex クラス] にアクセスします。 2. 認証プロバイダクラスの横にある [編集] をクリックします。デフォルトのクラス名は、 「AutocreatedRegHandlerxxxxxx…」で始まります。 247 Mobile SDK アプリケーションでの Communities の使用 Salesforce コミュニティを設定する 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. [保存] をクリックします。 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 248 Mobile SDK アプリケーションでの Communities の使用 Salesforce コミュニティを設定する 既存ユーザをリンクする URLを作成するには、sso を link に置き換えます。 https://login.salesforce.com/services/auth/link/00Da0000000TPNEAA4/ FB_Community_Login?community= https://mobilesdk-developer-edition.server_instance.force.com/fineapps 249 第 15 章 Mobile SDK でのマルチユーザのサポート トピック: • • マルチユーザのサポートについて マルチユーザのサポートの実装 複数のユーザが同時にログインできるようにするために、Mobile SDK には、ユーザの切り替えの基本的な実装と、Android、iOS、およびハ イブリッドアプリケーション用の API が用意されています。 Mobile SDK には、認証されたアカウントから選択できるデフォルトの ダイアログボックスが用意されています。アプリケーションでこのダ イアログボックスを起動する手段を実装し、ユーザの切り替えフロー を開始する API をコールします。 250 Mobile SDK でのマルチユーザのサポート マルチユーザのサポートについて マルチユーザのサポートについて バージョン 2.2 以降、Mobile SDK では、複数のユーザアカウントから同時にログインできます。これらのアカウ ントは、同じ組織の異なるユーザか、異なる組織 (本番組織と Sandbox 組織など) の異なるユーザを表します。 ユーザがログインすると、サーバに対して再認証することなくアカウント間のシームレスな切り替えを行うこと ができるようにそのユーザのログイン情報が保存されます。複数のログインをサポートしない場合は、アプリ ケーションを変更する必要はありません。既存の Mobile SDK API は、シングルユーザの場合と同じように機能 します。 Mobile SDK では、各ユーザアカウントが、認証された他のユーザアカウントに関連していないと想定していま す。それに応じて、Mobile SDK では、各アカウントに関連付けられたデータと他のすべてのユーザのデータが 分離されます。これにより、アカウント間でデータが混じることを回避できます。データの分離により、アカウ ントに関連付けられた SharedPreferences ファイル、SmartStore データベース、AccountManager データ、お よびその他のフラットファイルが保護されます。 次の Mobile SDK サンプルアプリケーションでは、マルチユーザの切り替えについて説明します。 • Android ネイティブ (SmartStore なし): RestExplorer • Android ネイティブ (SmartStore あり): NativeSqlAggregator • iOS ネイティブ: RestAPIExplorer • iOS ハイブリッド: ContactExplorer • ハイブリッド (SmartStore なし): ContactExplorer • ハイブリッド (SmartStore あり): AccountEditor マルチユーザのサポートの実装 Mobile SDK では、ネイティブ Android、ネイティブ iOS、およびハイブリッドアプリケーションでマルチユーザ のサポートを有効にする API が用意されています。 Mobile SDK では基礎となる機能は実装されますが、アプリケーションで API をコールして別のユーザに切り替 えない限り、実行時にマルチユーザの切り替えが初期化されません。ユーザを切り替える API は次のとおりで す。 Android ネイティブ (UserAccountManager クラスメソッド) public void switchToUser(UserAccount user) public void switchToNewUser() iOS ネイティブ (SFUserAccountManager クラスメソッド) - (void)switchToUser:(SFUserAccount *)newCurrentUser (ページ 262) - (void)switchToNewUser (ページ 262) ハイブリッド (JavaScript メソッド) switchToUser 251 Mobile SDK でのマルチユーザのサポート Android ネイティブ API ユーザが別のアカウントに切り替えるようにするには、ユーザインターフェースのボタン、メニュー、またはそ の他のコントロールから選択画面を起動します。Mobile SDK では、現在認証されているすべてのアカウントを ラジオボタンリストに表示する標準のマルチユーザの切り替え画面が用意されています。この画面をカスタマイ ズすることも、デフォルトバージョンをそのまま表示することもできます。ユーザが選択すると、マルチユーザ フローを起動する Mobile SDK メソッドをコールします。 API の使用を開始する前に、Mobile SDK とアプリケーションの分業を理解しておくことが重要です。特に、以 下の管理方法を考慮してください。 • 転送通知 (アプリケーションでサポートしている場合) • SmartStore スープ (アプリケーションで SmartStore を使用している場合) • アカウント管理 転送通知のタスク Mobile SDK (すべてのアカウント): • • • ログイン時に転送通知を登録する ログアウト時に転送通知を登録解除する 転送通知を配信する アプリケーション • • 対象ユーザアカウントに応じて通知を識別する 適切なユーザコンテキストを起動して各通知を表示する SmartStore スープのタスク Mobile SDK (すべてのアカウント): • • 認証されたユーザアカウントごとに個別の SmartStore データベースを作成する ユーザの切り替えが発生するたびに適切なバッキングデータベースに切り替える アプリケーション • ユーザの切り替えまたはログアウトが発生するたびに、キャッシュされたログイン情報 (メモリに保持された SmartStore のインスタンスなど) を更新する アカウント管理のタスク Mobile SDK (すべてのアカウント): • ユーザの切り替えが発生するたびに適切なアカウントログイン情報を読み込む アプリケーション • ユーザの切り替えまたはログアウトが発生するたびに、キャッシュされたログイン情報 (メモリに保持された RestClient のインスタンスなど) を更新する Android ネイティブ API Mobile SDK for Android のネイティブクラスは、マルチユーザのサポートの大半の作業を行います。アプリケー ションは、いくつかの簡単なコールを行い、メモリにキャッシュされたすべてのデータを処理します。ユーザの 切り替えアクティビティをカスタマイズすることもできます。 252 Mobile SDK でのマルチユーザのサポート Android ネイティブ API 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 コアがす べてのパスで実行フローを処理します。次のダイアグラムに、このフローを示します。 UserAccount クラス UserAccount クラスは、現在認証されている単一のユーザアカウントを表します。このクラスは、ユーザアカ ウントを一意に識別するために使用できるデータをカプセル化します。 253 Mobile SDK でのマルチユーザのサポート UserAccount クラス UserAccountManager クラス UserAccountManager クラスは、認証されたアカウントへのアクセス、新しいアカウントの追加、既存のアカ ウントのログアウト、既存のアカウント間の切り替えを行うメソッドを提供します。 AccountSwitcherActivity クラス AccountSwitcherActivity クラスを使用または拡張して、ユーザの切り替えのインターフェースを表示しま す。 UserSwitchReceiver クラス ネイティブ Android アプリケーションがトークン以外のデータをキャッシュする場合、UserSwitchReceiver 抽象クラスを実装して、ユーザの切り替えイベントの通知を受信します。 UserAccount クラス UserAccount クラスは、現在認証されている単一のユーザアカウントを表します。このクラスは、ユーザアカ ウントを一意に識別するために使用できるデータをカプセル化します。 コンストラクタ JSON オブジェクトまたはバンドルから直接 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 ) 指定した値を使用して UserAccount オブジェクトを作 成します。 public UserAccount(JSONObject object) JSON 文字列から UserAccount オブジェクトを作成し ます。 public UserAccount(Bundle bundle) Android アプリケーションバンドルから UserAccount オブジェクトを作成します。 メソッド メソッド 説明 public String getOrgLevelStoragePath() このユーザアカウントの組織レベルのストレージパス (アプリケーションデータの上位レベルのディレクトリ に対する相対パス) を返します。上位レベルのディレク トリは files などになります。出力の形式 254 Mobile SDK でのマルチユーザのサポート メソッド UserAccount クラス 説明 は、/{orgID}/ になります。これは、同じ組織の複数 のユーザで共有できるデータのストレージパスです。 public String getUserLevelStoragePath() このユーザアカウントのユーザレベルのストレージパ ス (アプリケーションデータの上位レベルのディレクト リに対する相対パス) を返します。上位レベルのディレ クトリは files などになります。出力の形式 は、/{orgID}/{userID}/ になります。これは、組織 の特定のユーザに固有のデータのストレージパスです が、そのユーザがメンバーであるその組織内のすべて のコミュニティで共有されるデータのストレージパス でもあります。 public String getCommunityLevelStoragePath(String communityId) このユーザアカウントのコミュニティレベルのストレー ジパス (アプリケーションデータの上位レベルのディレ クトリに対する相対パス) を返します。上位レベルの ディレクトリは files などになります。出力の形式 は、/{orgID}/{userID}/{communityID}/ になりま す。communityID が null の場合、出力は /{orgID}/{userID}/internal/ のようになります。 これは、特定のコミュニティの特定のユーザに固有の データのストレージパスです。 public String getOrgLevelFilenameSuffix() このユーザアカウントの一意のサフィックスを返しま す。このサフィックスをファイルに追加して、組織レ ベルでこのアカウントを一意に識別できます。出力の 形式は、_{orgID} になります。これは、同じ組織の複 数のユーザで共有できるデータのサフィックスです。 public String getUserLevelFilenameSuffix() このユーザアカウントの一意のサフィックスを返しま す。このサフィックスをファイルに追加して、ユーザ レベルでこのアカウントを一意に識別できます。出力 の形式は、_{orgID}_{userID} になります。これは、 組織の特定のユーザに固有のデータのサフィックスで すが、そのユーザがメンバーであるその組織内のすべ てのコミュニティで共有されるデータのサフィックス でもあります。 public String getCommunityLevelFilenameSuffix(String communityId) このユーザアカウントの一意のサフィックスを返しま す。このサフィックスをファイルに追加して、コミュ ニティレベルでこのアカウントを一意に識別できます。 出力の形式は、_{orgID}_{userID}_{communityID} になります。communityID が null の場合、出力は _{orgID}_{userID}_internal のようになります。こ れは、特定のコミュニティの特定のユーザに固有のデー タのサフィックスです。 255 Mobile SDK でのマルチユーザのサポート UserAccountManager クラス UserAccountManager クラス UserAccountManager クラスは、認証されたアカウントへのアクセス、新しいアカウントの追加、既存のアカウ ントのログアウト、既存のアカウント間の切り替えを行うメソッドを提供します。 UserAccountManager のインスタンスは直接作成しません。代わりに、次のコールを使用してインスタンスを取 得します。 SalesforceSDKManager.getInstance().getUserAccountManager(); メソッド メソッド 説明 public UserAccount getCurrentUser() 現在有効なユーザアカウントを返します。 public List<UserAccount> getAuthenticatedUsers() 認証されたユーザアカウントのリストを返します。 public boolean doesUserAccountExist(UserAccount account) 指定されたユーザアカウントがすでに認証されている かどうかを確認します。 public void switchToUser(UserAccount user) 指定されたユーザアカウントにアプリケーションコン テキストを切り替えます。指定されたユーザアカウン トが無効または null の場合、このメソッドはログイン フローを起動します。 public void switchToNewUser() 新しいユーザがログインするためのログインフローを 起動します。 public void signoutUser(UserAccount userAccount, Activity frontActivity) 指定されたユーザをアプリケーションからログアウト させて、そのユーザのログイン情報を消去します。 AccountSwitcherActivity クラス AccountSwitcherActivity クラスを使用または拡張して、ユーザの切り替えのインターフェースを表示しま す。 AccountSwitcherActivity クラスは、マルチユーザログインを処理する画面を提供します。この画面では、既 存のユーザアカウントのリストが表示され、ユーザは既存のアカウントを切り替えたり、新しいアカウントにサ インインしたりできます。マルチユーザログインを有効にするには、次のコードを使用してアプリケーションの 任意の場所からアクティビティを起動します。 final Intent i = new Intent(this, SalesforceSDKManager.getInstance().getAccountSwitcherActivityClass()); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); this.startActivity(i); たとえば、ユーザインターフェースの「ユーザの切り替え」ボタンからこのアクティビティを起動できます。例 については、RestExplorer サンプルアプリケーションを参照してください。 256 Mobile SDK でのマルチユーザのサポート UserSwitchReceiver クラス 必要に応じて、XML を介して AccountSwitcherActivity をカスタマイズおよびスタイル設定できます。 さらに詳細に制御するために、AccountSwitcherActivity を拡張したり、独自のカスタムサブクラスに置き換 えたりできます。デフォルトクラスを置き換えるには、 SalesforceSDKManager.setAccountSwitcherActivityClass() をコールします。置き換わるアクティビティ クラス (AccountSwitcherActivity.class など) のクラスファイルに参照を渡します。 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 つのメソッドで実装が必要になります。 257 Mobile SDK でのマルチユーザのサポート iOS ネイティブ API メソッド名 説明 protected abstract void onUserSwitch(); このメソッドを実装して、ユーザの切り替えの発生時 にキャッシュされたユーザデータ (トークン以外) を処 理します。 iOS ネイティブ API Mobile SDK for iOS のネイティブクラスは、マルチユーザのサポートの大半の作業を行います。アプリケーショ ンは、いくつかの簡単なコールを行い、メモリにキャッシュされたすべてのデータを処理します。ユーザの切り 替えアクティビティをカスタマイズすることもできます。 Mobile SDK for iOS では、ユーザの切り替えをサポートするために、SalesforceSDKCore ライブラリの Security フォルダのネイティブクラスを定義します。クラスには、以下が含まれます。 • • SFUserAccount SFUserAccountManager 次セクションでは、これらのクラスについて簡単に説明します。完全な API リファレンスドキュメントについて は、http://forcedotcom.github.io/SalesforceMobileSDK-iOS/Documentation/SalesforceSDKCore/html/index.html を参 照してください。 SFUserAccount クラス SFUserAccount クラスは、現在認証されている単一のユーザアカウントを表します。このクラスは、ユーザア カウントを一意に識別するために使用できるデータをカプセル化します。 SFUserAccountManager クラス SFUserAccountManager クラスは、認証されたアカウントへのアクセス、新しいアカウントの追加、アカウン トのログアウト、アカウント間の切り替えを行うメソッドを提供します。 SFUserAccount クラス SFUserAccount クラスは、現在認証されている単一のユーザアカウントを表します。このクラスは、ユーザア カウントを一意に識別するために使用できるデータをカプセル化します。 プロパティ JSON オブジェクトまたはバンドルから直接 SFUserAccount オブジェクトを作成できます。 プロパティ 説明 @property (nonatomic, copy) NSSet *accessScopes このユーザのアクセス範囲。 @property (nonatomic, strong) SFOAuthCredentials *credentials; このユーザに関連付けられたログイン情報。 258 Mobile SDK でのマルチユーザのサポート プロパティ SFUserAccount クラス 説明 @property (nonatomic, strong) SFIdentityData このユーザに関連付けられた ID データ。 *idData; @property (nonatomic, copy, readonly) NSURL サーバ側の API を呼び出するために使用できる URL。 *apiUrl; この URL では、現在のコミュニティが考慮されます (使用可能な場合)。 @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) SFUserAccountAccessRestriction accessRestrictions; このユーザに関連付けられたアクセス制限。 @property (nonatomic, copy) NSString *communityId; 現在のコミュニティ ID (ユーザがコミュニティにログ インしている場合)。コミュニティにログインしていな い場合、このプロパティは nil になります。 @property (nonatomic, readonly, getter = isSessionValid) BOOL sessionValid; ユーザにアクセストークンがあり、有効なセッション だと想定される場合、YES を返します。 @property (nonatomic, copy) NSDictionary *customData; ユーザのカスタムデータ。このデータは逐次化できる ため、customData に含まれるオブジェクトは NSCoding プロトコルに準拠する必要があります。 グローバル関数 関数名 説明 NSString *SFKeyForUserAndScope (SFUserAccount 特定の範囲でこのユーザアカウントを一意に識別する *user, SFUserAccountScope scope); キーを返します。scope を SFUserAccountScopeGlobal に設定すると、ユーザア カウントに関係なく同じキーが返されます。 259 Mobile SDK でのマルチユーザのサポート SFUserAccountManager クラス SFUserAccountManager クラス SFUserAccountManager クラスは、認証されたアカウントへのアクセス、新しいアカウントの追加、アカウン トのログアウト、アカウント間の切り替えを行うメソッドを提供します。 シングルトン SFUserAccountManager インスタンスにアクセスするには、次のメッセージを送信します。 [SFUserAccountManager sharedInstance] プロパティ プロパティ 説明 @property (nonatomic, strong) SFUserAccount *currentUser 現在のユーザアカウント。 ユーザがログインしていな い場合、このプロパティは nil になる可能性がありま す。 @property (nonatomic, readonly) NSString *currentUserId 現在のユーザの ID を取得する便利なプロパティ。この プロパティは、currentUser.credentials.userId の別名です。 @property (nonatomic, readonly) NSString *currentCommunityId 現在のユーザのコミュニティ ID を取得する便利なプロ パティ。このプロパティは、 currentUser.communityId の別名です。 @property (nonatomic, readonly) NSArray *allUserAccounts アプリケーションのすべての SFUserAccount インスタ ンスの NSArray。 @property (nonatomic, readonly) NSArray *allUserIds すべてのユーザ ID を含む配列を返します。 @property (nonatomic, copy) NSString *activeUserId 最後の有効なユーザ ID。activeUserId によって指定 されたユーザがアカウントリストから削除されている と、このユーザは現在のユーザとは一時的に異なる場 合があります。 @property (nonatomic, strong) NSString *loginHost ログインに使用されるホスト。 @property (nonatomic, assign) BOOL retryLoginAfterFailure ログインプロセスが失敗した場合にログインプロセス を再起動するかどうかを制御するフラグ。デフォルト 値は YES です。 @property (nonatomic, copy) NSString *oauthClientId ログインに使用される OAuth クライアント ID。この プロパティは、ログイン前にアプリケーションによっ てカスタマイズされている場合があります。カスタマ イズされていない場合、この値は、設定バンドルで設 定された SFDCOAuthClientIdPreference プロパティ によって決まります。 @property (nonatomic, copy) NSString *oauthCompletionUrl OAuth ログインプロセスに使用される OAuth コール バック URL。このプロパティは、ログイン前にアプリ ケーションによってカスタマイズされている場合があ ります。デフォルトでは、プロパティの値は、メイン 260 Mobile SDK でのマルチユーザのサポート SFUserAccountManager クラス プロパティ 説明 バンドルの SFDCOAuthRedirectUri プロパティからコ ピーされます。デフォルト値は、 @"sfdc:///axm/detect/oauth/done" です。 アプリケーションに関連付けられた OAuth 範囲。 @property (nonatomic, copy) NSSet *scopes メソッド メソッド 説明 - (NSString*)userAccountPlistFileForUser:(SFUserAccount*)user 指定されたユーザアカウントの .plist ファイルのパスを返しま す。 - (void)addDelegate:(id<SFUserAccountManagerDelegate>)delegate このユーザアカウントマネージャ に代理を追加します。 このユーザアカウントマネージャ (void)removeDelegate:(id<SFUserAccountManagerDelegate>)delegate から代理を削除します。 - (SFLoginHostUpdateResult *)updateLoginHost アプリケーション設定でアプリ ケーションレベルのログインホ ストをこの値に設定します。 - (BOOL)loadAccounts:(NSError**)error すべてのアカウントを読み込み ます。 - (BOOL)saveAccounts:(NSError**)error すべてのアカウントを保存しま す。 - (SFUserAccount*)createUserAccount すべてのアカウント情報を自分 自身で設定する場合に空のユー ザアカウントを作成するために 使用できます。それ以外の場合 は、必要に応じて [SFAuthenticationManager loginWithCompletion:failure:] を使用し、アカウントを自動的 に作成します。 - (SFUserAccount*)userAccountForUserId:(NSString*)userId 特定のユーザ ID に関連付けられ たユーザアカウントを返します。 - (NSArray *)accountsForOrgId:(NSString *)orgId 特定の組織にアクセスできるす べてのアカウントを返します。 - (NSArray *)accountsForInstanceURL:(NSString *)instanceURL 特定のインスタンス URL に一致 するすべてのアカウントを返し ます。 - (void)addAccount:(SFUserAccount *)acct ユーザアカウントを追加します。 261 Mobile SDK でのマルチユーザのサポート ハイブリッド API メソッド 説明 - (BOOL)deleteAccountForUserId:(NSString*)userId error:(NSError 特定のユーザ ID に関連付けられ **)error たユーザアカウントを削除しま す。 - (void)clearAllAccountState メモリ内のアカウントの状態を クリアします (ただし、ディスク の内容は何も変更されません)。 - (void)applyCredentials:(SFOAuthCredentials*)credentials 指定されたログイン情報を現在 のユーザに適用します。ユーザ が存在しない場合、ユーザが作 成されます。 - (void)applyCustomDataToCurrentUser:(NSDictionary *)customData そのユーザの Sandbox の外部か らアクセスできる SFUserAccount にカスタムデー タを適用します。このデータは、 アプリケーションの起動ごとに 変わることはありません。この データは逐次化されるため、 customData に含まれるオブジェ クトが NSCoding プロトコルに 準拠していることを確認してく ださい。 重要: このメソッドは、 機密情報以外にのみに使 用します。 - (void)switchToNewUser 現在のユーザから新しいユーザ コンテキストに切り替えます。 - (void)switchToUser:(SFUserAccount *)newCurrentUser 現在のユーザを指定されたユー ザアカウントに切り替えます。 - (void)userChanged:(SFUserAccountChange)change 現在のユーザに何らかの変更が あったことを SFUserAccountManager オブ ジェクトに通知します。 ハイブリッド API ハイブリッドアプリケーションは、Mobile SDK JavaScript API を介して、マルチユーザのサポートを有効にでき ます。これらの API は、SFAccountManagerPlugin Cordova ベースのモジュールにあります。 262 Mobile SDK でのマルチユーザのサポート ハイブリッド API SFAccountManagerPlugin メソッド メソッド名 説明 getUsers すでにログインしているユーザのリストを返します。 getCurrentUser 現在の有効なユーザを返します。 logout ユーザが渡された場合は指定されたユーザをログアウ トさせます。引数を指定しないでコールした場合は、 現在のユーザをログアウトさせます。 switchToUser 指定したユーザにアプリケーションコンテキストを切 り替えます。ユーザが指定されていない場合は、アカ ウントの切り替え画面を起動します。 ハイブリッドアプリケーションでは、マルチユーザの切り替えのブロードキャストイベントのレシーバを実装す る必要はありません。このハンドラは、SalesforceDroidGapActivity クラスで実装されます。 263 第 16 章 以前のリリースからの移行 トピック: • • • Mobile SDK Android アプリケー ションを 2.1 から 2.2 に移行する Mobile SDK iOS アプリケーション を 2.1 から 2.2 に移行する 以前のリリースからの移行 Salesforce Mobile SDK 2.1 を使用してコードを開発した場合は、次の手 順に従ってアプリケーションをバージョン 2.2 に更新します。 Salesforce Mobile SDK のバージョン 1.5 または 2.0 を使用するアプリ ケーションをアップグレードする場合は、以前のリリースからの移行 を参照してください。 264 以前のリリースからの移行 Mobile SDK Android アプリケーションを 2.1 から 2.2 に 移行する Mobile SDK Android アプリケーションを 2.1 から 2.2 に移行す る Android アプリケーション (ネイティブまたはハイブリッド) を Salesforce Mobile SDK 2.1 からバージョン 2.2 に アップグレードするには、次のタスクを実行します。 1. Eclipse で、既存の SalesforceSDK プロジェクトを Mobile SDK 2.2 SalesforceSDK プロジェクトに置き換えます。 2. アプリケーションで SmartStore を使用する場合は、Eclipse で既存の SmartStore プロジェクトを Mobile SDK 2.2 SmartStore プロジェクトに置き換えます。 3. プロジェクトを右クリックし、[プロパティ] を選択します。 4. [Android] を選択します。 5. [ライブラリ] セクションで、既存の SalesforceSDK エントリをワークスペースの Mobile SDK 2.2 SalesforceSDK プロジェクトに置き換えます。 6. アプリケーションで SmartStore を使用する場合は、[ライブラリ] セクションの既存の SmartStore エントリを ワークスペースの Mobile SDK 2.2 SmartStore プロジェクトに置き換えます。 Mobile SDK iOS アプリケーションを 2.1 から 2.2 に移行する 重要: ネイティブアプリケーションとハイブリッドアプリケーションをアップグレードするには、更新さ れた forceios npm パッケージを使用して新しいアプリケーションを作成し、既存のコードおよびリソース を新しいアプリケーションに移行することを強くお勧めします。 以下の手動のステップは、既存のアプリケーションで Mobile SDK アイテムを更新する場合にのみ実行してくだ さい。 iOS ハイブリッドアプリケーション Mobile SDK ライブラリパッケージを更新する Mobile SDK ライブラリパッケージを簡単にアップグレードするには、アプリケーションの Xcode オブジェクト の Dependencies フォルダを削除してから、新しいライブラリを追加します。 1. Xcode プロジェクトのプロジェクトナビゲータで、Dependencies フォルダを探します。Ctrl キーを押しなが らフォルダをクリックし、[Delete (削除)]、[Move to Trash (ゴミ箱に移動)] の順に選択します。 2. 次のバイナリパッケージを配布リポジトリからダウンロードします。 • • • • • Cordova/Cordova-Release.zip SalesforceHybridSDK-Release.zip SalesforceOAuth-Release.zip SalesforceSDKCore-Release.zip SalesforceSecurity-Release.zip 3. また、次のフォルダも配布リポジトリの ThirdParty フォルダリンクからダウンロードします。 • SalesforceCommonUtils 265 以前のリリースからの移行 • • SalesforceSecurity ヘッダーファイルの検索パスを追加す る openssl sqlcipher 4. Dependencies フォルダをアプリケーションフォルダの下に再作成します。 5. Dependencies フォルダに、ステップ 2 の新しいパッケージを解凍し、ステップ 3 のフォルダをコピーしま す。 6. プロジェクトナビゲータで、Ctrl キーを押しながらアプリケーションフォルダをクリックし、[Add Files to "<app_name>” (「<app_name>」にファイルを追加)] を選択します。 7. Dependencies フォルダを選択し、[Create groups for any added folder (追加されたフォルダのグループを作成 する)] が選択されていることを確認します。 8. [Add (追加)] をクリックします。 SalesforceSecurity ヘッダーファイルの検索パスを追加する Xcode プロジェクトのヘッダーファイル検索パスを更新します。 1. プロジェクトナビゲータで、プロジェクトを選択します。 2. メインターゲットの [Build Settings (ビルド設定)] タブを選択します。 3. [Header Search Paths (ヘッダー検索パス)] までスクロールダウン (または検索/絞り込み) します。 4. 次の検索パスを追加します。 • $(SRCROOT)/[App Name]/Dependencies/SalesforceSecurity/Headers ハイブリッドローカルアイテムを更新する 1. ハイブリッド「ローカル」アプリケーションの場合は、アプリケーションの www/ フォルダにある次のファイ ルを、SalesforceMobileSDK-Shared repo の libs フォルダにある新バージョンのファイルに置き換えます。 • • • cordova.force.js forcetk.mobilesdk.js smartsync.js AppDelegate 実装を更新する ログアウトイベントおよびログインホストの変更イベントの処理パターンと共に、一部のユーザ管理 API が変更 されました。変更を確認する場合、2.2 バージョンの forceios ハイブリッドアプリケーションから AppDelegate コードを参照することをお勧めします。次に、変更内容の概要を示します。 • ログアウトイベントの通知とログインホストの変更が代理メソッドに移行しました。 SFAuthenticationManagerDelegate および SFUserAccountManagerDelegate 代理メソッドを実装するよ うに AppDelegate クラスを更新します。 ◊ ユーザログアウトの通知の場合、[SFAuthenticationManagerDelegate authManagerDidLogout:] を 使用します。 ◊ ログインホストの変更の場合、[SFUserAccountManagerDelegate userAccountManager:didSwitchFromUser:toUser:] を使用します。 266 以前のリリースからの移行 iOS ネイティブアプリケーション メモ: [設定] でログインホストを変更すると、実質的にアプリケーションで新しいユーザへの切り 替えが行われ、ログインが要求されます。 iOS ネイティブアプリケーション Mobile SDK ライブラリパッケージを更新する Mobile SDK ライブラリパッケージを簡単にアップグレードするには、アプリケーションの Xcode オブジェクト の Dependencies フォルダを削除してから、新しいライブラリを追加します。 1. Xcode プロジェクトのプロジェクトナビゲータで、Dependencies フォルダを探します。Ctrl キーを押しなが らフォルダをクリックし、[Delete (削除)]、[Move to Trash (ゴミ箱に移動)] の順に選択します。 2. 次のバイナリパッケージを配布リポジトリからダウンロードします。 • • • • • MKNetworkKit-iOS-Release.zip SalesforceNetworkSDK-Release.zip SalesforceOAuth-Release.zip SalesforceSDKCore-Release.zip SalesforceSecurity-Release.zip 3. また、次のフォルダも配布リポジトリの ThirdParty フォルダリンクからダウンロードします。 • • • SalesforceCommonUtils openssl sqlcipher 4. Dependencies フォルダをアプリケーションフォルダの下に再作成します。 5. Dependencies フォルダに、ステップ 2 の新しいパッケージを解凍し、ステップ 3 のフォルダをコピーしま す。 6. プロジェクトナビゲータで、Ctrl キーを押しながらアプリケーションフォルダをクリックし、[Add Files to "<app_name>” (「<app_name>」にファイルを追加)] を選択します。 7. Dependencies フォルダを選択し、[Create groups for any added folder (追加されたフォルダのグループを作成 する)] が選択されていることを確認します。 8. [Add (追加)] をクリックします。 SalesforceSecurity ヘッダーファイルの検索パスを追加する SalesforceSecurity プロジェクトを検索できるようにヘッダーファイル検索パスを更新します。 1. プロジェクトナビゲータで、プロジェクトを選択します。 2. メインターゲットの [Build Settings (ビルド設定)] タブを選択します。 3. [Header Search Paths (ヘッダー検索パス)] までスクロールダウン (または検索/絞り込み) します。 4. 次の検索パスを追加します。 • $(SRCROOT)/[App Name]/Dependencies/SalesforceSecurity/Headers 267 以前のリリースからの移行 パスコード関連のコードを新しい SalesforceSecurity クラ スに移行する パスコード関連のコードを新しい SalesforceSecurity クラスに移行する SalesforceSecurity は、2.2 の新しいライブラリです。多くのセキュリティ関連のクラス (特にパスコード管 理関連のクラス) が SalesforceSDKCore から SalesforceSecurity に移行しました。SalesforceSDKCore の パスコード関連の機能をコードで参照している場合、SalesforceSecurity の対応する適切な機能を使用するよ うにそのコードを更新してください。 AppDelegate 実装を更新する ログアウトイベントおよびログインホストの変更イベントの処理パターンと共に、一部のユーザ管理 API が変更 されました。変更を確認する場合、2.2 バージョンの forceios ネイティブアプリケーションから AppDelegate コー ドを参照することをお勧めします。次に、変更内容の概要を示します。 • SFAccountManager の代わりに SFUserAccountManager を使用して、接続アプリケーション設定を指定しま す。次の表に、使用されなくなったコードとそれに置き換わるコードを示します。 • 置換前... ...置換後 [SFAccountManager setClientId:] [SFUserAccountManager sharedInstance].oauthClientId [SFAccountManager setRedirectUri:] [SFUserAccountManager sharedInstance].oauthCompletionUrl [SFAccountManager setScopes:] [SFUserAccountManager sharedInstance].scopes ログアウトイベントの通知とログインホストの変更が代理メソッドに移行しました。 SFAuthenticationManagerDelegate および SFUserAccountManagerDelegate 代理メソッドを実装するよ うに AppDelegate クラスを更新します。 ◊ ユーザログアウトの通知の場合、[SFAuthenticationManagerDelegate authManagerDidLogout:] を 使用します。 ◊ ログインホストの変更の場合、[SFUserAccountManagerDelegate userAccountManager:didSwitchFromUser:toUser:] を使用します。 メモ: [設定] でログインホストを変更すると、実質的にアプリケーションで新しいユーザへの切り 替えが行われ、ログインが要求されます。 以前のリリースからの移行 以前のリリースよりも古いバージョンから移行するには、現在のバージョンから始めて、介在するリリースごと にコードのアップグレード手順を実行します。 268 以前のリリースからの移行 バージョン 2.0 からバージョン 2.1 への移行 バージョン 2.0 からバージョン 2.1 への移行 Salesforce Mobile SDK 2.0 を使用してコードを開発した場合は、次の手順に従ってアプリケーションをバージョン 2.1 に更新します。 Mobile SDK Android アプリケーションを 2.0 から 2.1 に移行する Android アプリケーション (ネイティブまたはハイブリッド) を Salesforce Mobile SDK 2.0 からバージョン 2.1 に アップグレードするには、次のタスクを実行します。 1. Eclipse で、既存の SalesforceSDK プロジェクトを Mobile SDK 2.1 SalesforceSDK プロジェクトに置き換えます。 2. (省略可能) アプリケーションで SmartStore を使用する場合は、Eclipse で既存の SmartStore プロジェクトを Mobile SDK 2.1 SmartStore プロジェクトに置き換えます。 3. プロジェクトを右クリックし、[プロパティ] を選択します。 4. [Android] を選択します。 5. ワークスペースで、ライブラリプロジェクトセクションにある既存の SalesforceSDK エントリを新しい SalesforceSDK プロジェクトに置き換えます。 6. (省略可能) アプリケーションで SmartStore を使用する場合は、ワークスペースで、ライブラリプロジェクト セクションにある既存の SmartStore エントリを新しい SmartStore プロジェクトに置き換えます。 Salesforce Mobile SDK の Activity および Service 宣言は、アプリケーションの AndroidManifest.xml ファイル から SalesforceSDK プロジェクトの AndroidManifest.xml ファイルに移動済みです。manifestmerger 属性 を有効にすると、この設定がアプリケーションのマニフェストファイルに自動的にマージされます。 7. 次のコードをアプリケーションの project.properties ファイルに追加します。 manifestmerger.enabled=true メモ: このステップは、転送通知などの一部の新しい Mobile SDK 2.1 機能を使用するために実行する必要が あります。 Mobile SDK iOS アプリケーションを 2.0 から 2.1 に移行する ネイティブアプリケーションとハイブリッドアプリケーションをアップグレードするには、forceios npm パッケー ジのアプリケーションテンプレートから新しいアプリケーションを作成し、アプリケーション固有のアイテムを 新しいテンプレートに追加することを強くお勧めします。 以下の手動のステップは、既存のアプリケーションで Mobile SDK アイテムを更新する場合にのみ実行してくだ さい。 269 以前のリリースからの移行 Mobile SDK iOS アプリケーションを 2.0 から 2.1 に移行 する iOS ハイブリッドアプリケーション Mobile SDK ライブラリパッケージを更新する Mobile SDK ライブラリパッケージを簡単にアップグレードするには、アプリケーションの Xcode オブジェクト の Dependencies フォルダを削除してから、新しいライブラリを追加します。 1. Xcode プロジェクトのプロジェクトナビゲータで、Dependencies フォルダを探します。Ctrl キーを押しなが らフォルダをクリックし、[Delete (削除)]、[Move to Trash (ゴミ箱に移動)] の順に選択します。 2. 次のバイナリパッケージを配布リポジトリからダウンロードします。 • • • • Cordova/Cordova-Release.zip SalesforceHybridSDK-Release.zip SalesforceOAuth-Release.zip SalesforceSDKCore-Release.zip 3. また、次のフォルダも配布リポジトリの ThirdParty フォルダリンクからダウンロードします。 • • • SalesforceCommonUtils openssl sqlcipher 4. Dependencies フォルダをアプリケーションフォルダの下に再作成します。 5. Dependencies フォルダに、ステップ 2 の新しいパッケージを解凍し、ステップ 3 のフォルダをコピーしま す。 6. プロジェクトナビゲータで、Ctrl キーを押しながらアプリケーションフォルダをクリックし、[Add Files to "<app_name>” (「<app_name>」にファイルを追加)] を選択します。 7. Dependencies フォルダを選択し、[Create groups for any added folder (追加されたフォルダのグループを作成 する)] が選択されていることを確認します。 8. [Add (追加)] をクリックします。 ヘッダーファイルの検索パスを更新する Xcode プロジェクトのヘッダーファイル検索パスを更新します。 1. プロジェクトナビゲータで、プロジェクトを選択します。 2. メインターゲットの [Build Settings (ビルド設定)] タブを選択します。 3. [Header Search Paths (ヘッダー検索パス)] までスクロールダウン (または検索/絞り込み) します。 4. 次の検索パスを追加します。 • • • • $(SRCROOT)/[App Name]/Dependencies/SalesforceSDKCore/Headers $(SRCROOT)/[App Name]/Dependencies/SalesforceOAuth/Headers $(SRCROOT)/[App Name]/Dependencies/SalesforceCommonUtils/Headers $(SRCROOT)/[App Name]/Dependencies/SalesforceHybridSDK/Headers ハイブリッドローカルアイテムを更新する 1. ハイブリッド「ローカル」アプリケーションの場合は、アプリケーションの www/ フォルダにある次のファイ ルを、SalesforceMobileSDK-Shared repo の libs フォルダにある新バージョンのファイルに置き換えます。 • • cordova.force.js forcetk.mobilesdk.js 270 以前のリリースからの移行 • Mobile SDK iOS アプリケーションを 2.0 から 2.1 に移行 する smartsync.js iOS ネイティブアプリケーション Mobile SDK ライブラリパッケージを更新する Mobile SDK ライブラリパッケージを簡単にアップグレードするには、アプリケーションの Xcode オブジェクト の Dependencies フォルダを削除してから、新しいライブラリを追加します。 1. Xcode プロジェクトのプロジェクトナビゲータで、Dependencies フォルダを探します。Ctrl キーを押しなが らフォルダをクリックし、[Delete (削除)]、[Move to Trash (ゴミ箱に移動)] の順に選択します。 2. 次のバイナリパッケージを配布リポジトリからダウンロードします。 • • • • • Cordova/Cordova-Release.zip SalesforceHybridSDK-Release.zip SalesforceNetworkSDK-Release.zip SalesforceOAuth-Release.zip SalesforceSDKCore-Release.zip 3. また、次のフォルダも配布リポジトリの ThirdParty フォルダリンクからダウンロードします。 • • • SalesforceCommonUtils openssl sqlcipher 4. Dependencies フォルダをアプリケーションフォルダの下に再作成します。 5. Dependencies フォルダに、ステップ 2 の新しいパッケージを解凍し、ステップ 3 のフォルダをコピーしま す。 6. プロジェクトナビゲータで、Ctrl キーを押しながらアプリケーションフォルダをクリックし、[Add Files to "<app_name>” (「<app_name>」にファイルを追加)] を選択します。 7. Dependencies フォルダを選択し、[Create groups for any added folder (追加されたフォルダのグループを作成 する)] が選択されていることを確認します。 8. [Add (追加)] をクリックします。 ヘッダーファイルの検索パスを更新する Xcode プロジェクトのヘッダーファイル検索パスを更新します。 1. プロジェクトナビゲータで、プロジェクトを選択します。 2. メインターゲットの [Build Settings (ビルド設定)] タブを選択します。 3. [Header Search Paths (ヘッダー検索パス)] までスクロールダウン (または検索/絞り込み) します。 4. 次の検索パスを追加します。 • • • • • $(SRCROOT)/[App Name]/Dependencies/SalesforceSDKCore/Headers $(SRCROOT)/[App Name]/Dependencies/SalesforceOAuth/Headers $(SRCROOT)/[App Name]/Dependencies/SalesforceNetworkSDK/Headers $(SRCROOT)/[App Name]/Dependencies/SalesforceCommonUtils/Headers $(SRCROOT)/[App Name]/Dependencies/SalesforceHybridSDK/Headers 271 以前のリリースからの移行 バージョン 1.5 からバージョン 2.0 への移行 ネイティブ Mobile SDK ライブラリの変更 バージョン 2.1 では、Mobile SDK の RestKit が、ネイティブアプリケーションのネットワークライブラリとして MKNetworkKit に置き換えられました。MKNetworkKit は新しい SalesforceNetworkSDK ライブラリでラップされ ており、このライブラリは SFRestAPI クラスおよびそのサポートクラスでラップされています。ほとんどのイ ンターフェースに変更はありません。重要な変更のリストを次に示します。 • [SFRestAPI sharedInstance].rkClient は存在しなくなりました。 • [SFRestAPI send:delegate:] で、要求に関連付けられた新しい SFNetworkOperation が返されるように なりました。 • SFRestRequest.networkOperation では、要求に関連付けられた基盤の SFNetworkOperation オブジェク トがポイントされます。 アプリケーションでネットワーク用に基盤の RestKit メンバーを使用していた場合は、MKNetworkKit ライブラ リと SalesforceNetworkSDK ライブラリの同等の機能を確認する必要があります。 バージョン 1.5 からバージョン 2.0 への移行 Salesforce Mobile SDK 1.5 を使用してコードを開発した場合は、次の手順に従ってアプリケーションをバージョン 2.0 に更新します。 Mobile SDK Android アプリケーションを 1.5 から 2.0 に移行する Android アプリケーションを Salesforce Mobile SDK 1.5.3 からバージョン 2.0.0 にアップグレードするには、次の タスクを実行します。 ネイティブ Android アプリケーションのアップグレード • アプリケーションの Eclipse ワークスペースで、既存の SalesforceSDK プロジェクトを 2.0 SalesforceSDK プロ ジェクトに置き換えます。アプリケーションで SmartStore を使用する場合は、Eclipse で既存の SmartStore プ ロジェクトを 2.0 SmartStore プロジェクトに置き換えます。 1. プロジェクトを右クリックし、[プロパティ] を選択します。 2. Android タブをクリックし、ワークスペースで一番下 (ライブラリプロジェクトセクション) にある既存 の SalesforceSDK エントリを新しい SalesforceSDK プロジェクトに置き換えます。アプリケーションで SmartStore を使用する場合は、SmartStore プロジェクトでこの手順を繰り返します。 • ForceApp または ForceAppWithSmartStore を拡張するクラスを、Application を拡張するように変更しま す。このクラス SampleApp は、残りの手順でコールします。 • KeyInterface を実装する新しいクラスを作成します。そのクラスに KeyImpl という名前 (または任意の別 の名前) を付けます。getKey() の実装を SampleApp から KeyImpl に移動します。 • ForceApp を SalesforceSDKManager という名前に変更し、ForceAppWithSmartStore を SalesforceSDKManagerWithSmartStore という名前に変更しました。 ◊ ForceApp のすべてのインスタンスを SalesforceSDKManager に置き換えます。 ◊ ForceAppWithSmartStore のすべてのインスタンスを SalesforceSDKManagerWithSmartStore に置き 換えます。 272 以前のリリースからの移行 Mobile SDK Android アプリケーションを 1.5 から 2.0 に 移行する ◊ この変更が反映されるようにアプリケーションのクラスのインポートを更新します。 ◊ ForceApp.APP のすべてのインスタンスを SalesforceSDKManager.getInstance() に置き換えます。 ◊ ForceAppWithSmartStore.APP のすべてのインスタンスを SalesforceSDKManagerWithSmartStore.getInstance() に置き換えます。 • SampleApp の onCreate() メソッドに、次のコードを追加します。 SalesforceSDKManager.initNative(getApplicationContext(), new KeyImpl(), <mainActivityClass>.class); <mainActivityClass> は、ログインフローの完了時に起動するクラスです。 メモ: ◊ アプリケーションで独自のログインアクティビティを指定する場合は、それを追加の引数として initNative() メソッドコールに渡すことができます。 ◊ アプリケーションで SmartStore を使用する場合は、SalesforceSDKManager の代わりに SalesforceSDKManagerWithSmartStore で initNative() をコールします。 • ForceApp の上書きされたメソッド (getKey()、getMainActivityClass()、その他の上書きされたメソッ ドなど) を SampleApp から削除します。 • LoginOptions オブジェクトを作成する必要はなくなりました。Salesforce Mobile SDK によって、これらのオ プションが XML ファイル bootconfig.xml から自動的に読み取られます。このファイルはプロジェクトの res/values フォルダにあります。 ◊ プロジェクトの res/values フォルダに、bootconfig.xml というファイルを作成します。アプリケー ションのログインオプション設定を、コードから bootconfig.xml に移動します。例については、 SalesforceSDK プロジェクトまたはいずれかのサンプルネイティブアプリケーションにある res/values/bootconfig.xml を参照してください。 • NativeMainActivity は SalesforceActivity という名前に変更され、 com.salesforce.androidsdk.ui.sfnative という名前の新しいパッケージに移動されました。 ◊ アプリケーションのいずれかのクラスで NativeMainActivity を拡張する場合は、NativeMainActivity へのすべての参照を SalesforceActivity に置き換えます。 ◊ この変更が反映されるようにアプリケーションのクラスのインポートを更新します。 • SmartStore を com.salesforce.androidsdk.smartstore という名前の新しいパッケージに移動しました。 アプリケーションで SmartStore プロジェクトを使用する場合は、この変更が反映されるようにアプリケーショ ンのクラスのインポートと他のコード参照を更新します。 ハイブリッド Android アプリケーションのアップグレード • アプリケーションの Eclipse ワークスペースで、既存の SalesforceSDK プロジェクトを 2.0 SalesforceSDK プロ ジェクトに置き換えます。アプリケーションで SmartStore を使用する場合は、Eclipse で既存の SmartStore プ ロジェクトを 2.0 SmartStore プロジェクトに置き換えます。 1. プロジェクトを右クリックし、[プロパティ] を選択します。 273 以前のリリースからの移行 Mobile SDK Android アプリケーションを 1.5 から 2.0 に 移行する 2. Android タブをクリックし、ワークスペースで一番下 (ライブラリプロジェクトセクション) にある既存 の SalesforceSDK エントリを新しい SalesforceSDK プロジェクトに置き換えます。アプリケーションで SmartStore を使用する場合は、SmartStore プロジェクトでこの手順を繰り返します。 • ForceApp または ForceAppWithSmartStore を拡張するクラスを、Application を拡張するように変更しま す。このクラス SampleApp は、残りの手順でコールします。 • KeyInterface を実装する新しいクラスを作成します。そのクラスに KeyImpl という名前 (または任意の別 の名前) を付けます。getKey() の実装を SampleApp から KeyImpl に移動します。 • ForceApp を SalesforceSDKManager という名前に変更し、ForceAppWithSmartStore を SalesforceSDKManagerWithSmartStore という名前に変更しました。 ◊ ForceApp のすべてのインスタンスを SalesforceSDKManager に置き換えます。 ◊ ForceAppWithSmartStore のすべてのインスタンスを SalesforceSDKManagerWithSmartStore に置き 換えます。 ◊ この変更が反映されるようにアプリケーションのクラスのインポートを更新します。 ◊ ForceApp.APP のすべてのインスタンスを SalesforceSDKManager.getInstance() に置き換えます。 ◊ ForceAppWithSmartStore.APP のすべてのインスタンスを SalesforceSDKManagerWithSmartStore.getInstance() に置き換えます。 • SampleApp の onCreate() メソッドに、次のコードを追加します。 SalesforceSDKManager.initHybrid(getApplicationContext(), new KeyImpl()); メモ: ◊ アプリケーションで独自のログインアクティビティを指定する場合は、それを追加の引数として initHybrid() メソッドコールに渡すことができます。 ◊ アプリケーションで SmartStore を使用する場合は、SalesforceSDKManager の代わりに SalesforceSDKManagerWithSmartStore で initHybrid() をコールします。 • ForceApp の上書きされたメソッド (getKey()、getMainActivityClass()、その他の上書きされたメソッ ドなど) を SampleApp から削除します。 • LoginOptions オブジェクトを作成する必要はなくなりました。Salesforce Mobile SDK によって、これらのオ プションが XML ファイル bootconfig.xml から自動的に読み取られます。このファイルはプロジェクトの res/values フォルダにあります。 ◊ プロジェクトの res/values フォルダに、bootconfig.xml というファイルを作成します。アプリケー ションのログインオプション設定を、コードから bootconfig.xml に移動します。例については、 SalesforceSDK プロジェクトまたはいずれかのサンプルネイティブアプリケーションにある res/values/bootconfig.xml を参照してください。 • NativeMainActivity は SalesforceActivity という名前に変更され、 com.salesforce.androidsdk.ui.sfnative という名前の新しいパッケージに移動されました。 274 以前のリリースからの移行 Mobile SDK iOS アプリケーションを 1.5 から 2.0 に移行 する ◊ アプリケーションのいずれかのクラスで NativeMainActivity を拡張する場合は、NativeMainActivity へのすべての参照を SalesforceActivity に置き換えます。 ◊ この変更が反映されるようにアプリケーションのクラスのインポートを更新します。 • SmartStore を com.salesforce.androidsdk.smartstore という名前の新しいパッケージに移動しました。 アプリケーションで SmartStore プロジェクトを使用する場合は、この変更が反映されるようにアプリケーショ ンのクラスのインポートと他のコード参照を更新します。 • bootconfig.js を bootconfig.json で置き換えました。既存の bootconfig.js を新しい bootconfig.json 形式に変換します。例については、「ハイブリッドサンプルアプリケーション」を参照してください。 • SalesforceSDK Cordova プラグイン (SFHybridApp.js、cordova.force.js、および SalesforceOAuthPlugin.js) は、filecordova.force.js という名前の 1 つのファイルに結合されました。 ◊ これらの Cordova プラグインファイルを cordova.force.js に置き換えます。 ◊ SFHybridApp.js、cordova.force.js、および SalesforceOAuthPlugin.js へのすべての参照を cordova.force.js に置き換えます。 • forcetk.js は forcetk.mobilesdk.js という名前に変更されました。forcetk.js の既存のコピーを最新 バージョンの forcetk.mobilesdk.js に置き換えます。forcetk.js へのすべての参照を新しい名前に更新 します。 • bootstrap.html ファイルは不要になったため、安全に削除できます。 • SalesforceDroidGapActivity および SalesforceGapViewClient を、 com.salesforce.androidsdk.ui.sfhybrid という名前の新しいパッケージに移動しました。アプリケー ションでこれらのクラスを参照する場合は、その参照および関連するクラスのインポートを更新します。 Mobile SDK iOS アプリケーションを 1.5 から 2.0 に移行する iOS アプリケーションを Salesforce Mobile SDK 1.5 からバージョン 2.0 にアップグレードするには、次のタスクを 実行します。 ネイティブ iOS アプリケーションのアップグレード すべてのアップグレードの場合と同様に、既存のアプリケーションをアップグレードするには 2 通りの方法があ ります。 • • アプリケーション種別 (ネイティブ、ハイブリッド) の Mobile SDK 2.0 テンプレートアプリケーションを使用 して新しいプロジェクトを作成し、既存のコードおよびアイテムを新しいアプリケーションに移動する。 Mobile SDK 2.0 アイテムを既存のアプリケーションに組み込む。 バージョン 2.0 の場合は、最初の方法を使用することを強くお勧めします。2 番目の方法を使用する場合でも、 サンプルアプリケーションを作成することで、AppDelegate クラスでワークフローの変更を確認できるという 利点があります。ネイティブとハイブリッドの両方で、親アプリケーションの代理クラス (SFNativeRestAppDelegate および SFContainerAppDelegate) がサポートされなくなりました。アプリケー ションの AppDelegate クラスで、起動プロセスが統制されるようになりました。 • 置き換えられた SalesforceHybridSDK.framework を削除します。 • Mobile SDK ライブラリとリソースの連動関係を SalesforceMobileSDK-iOS-Package repo から更新します。 275 以前のリリースからの移行 Mobile SDK iOS アプリケーションを 1.5 から 2.0 に移行 する ◊ SalesforceSDK を削除します。 ◊ SalesforceNativeSDK (Dependencies/ フォルダにある) を追加します。 ◊ SalesforceSDKCore (Dependencies/ フォルダにある) を追加します。 ◊ SalesforceOAuth (Dependencies/ フォルダにある) を更新します。 ◊ SalesforceSDKResources.bundle (Dependencies/ フォルダにある) を更新します。 ◊ RestKit (Dependencies/ThirdParty/RestKit/ フォルダにある) を更新します。 ◊ SalesforceCommonUtils (Dependencies/ThirdParty/SalesforceCommonUtils フォルダにある) を更 新します。 ◊ openssl (Dependencies/ThirdParty/openssl フォルダにある libcrypto.a と libssl.a) を更新します。 ◊ sqlcipher (Dependencies/ThirdParty/sqlcipher フォルダにある) を更新します。 • AppDelegate クラスを更新します。AppDelegate.h および AppDelegate.m ファイルを新しい設計パターン に適合します。次の重要なポイントを参考にしてください。 ◊ AppDelegate.h では、AppDelegate を SFNativeRestAppDelegate から継承しないようにする必要があ ります。 ◊ AppDelegate.m では、認証フローとルートビューコントローラのステージングの移動を AppDelegate で 主に行うようになりました。また、ユーザがログアウトしたりログインホストを切り替えたりするときの 境界イベントも処理します。 メモ: 新しい AppDelegate の設計パターンはあくまでも目安です。Mobile SDK に、特定のフロー は不要になりました。アプリケーションの起動および境界使用例に関して、ニーズに合った認証 フロー (更新された単一の SFAuthenticationManager を使用) を使用します。 ◊ 認証を使用する場合の唯一の前提条件は、SFAccountManager 構成設定が [AppDelegate init] の一番 上にあるということです。これらの設定が、接続アプリケーションで指定されたものと一致していること を確認します。また、[SFAuthenticationManager loginWithCompletion:failure:] に初めてコール する前に、この設定が完了していることも確認します。 ハイブリッド iOS アプリケーションのアップグレード Mobile SDK 2.0 では、ブートストラップ時のハイブリッド設定はネイティブコードに移動されます。 SFHybridViewController で、新しい設定を確認してください (この変更を、ハイブリッドテンプレートアプリ ケーションの AppDelegate で確認することもできます)。 新しいアプリケーションテンプレートが、forceios NPM パッケージで使用できるようになりました。テンプレー トをインストールするには、まず node.js をインストールします。テンプレートのインストールおよびそれを使 用したアプリケーションの作成についての詳細は、npmjs.org の forceios README を参照してください。 以前のコンテンツを 2.0 アプリケーションシェルにエクスポートしない場合でも、新しいハイブリッドアプリケー ションをテンプレートから作成して進めることをお勧めします。 • SalesforceHybridSDK.framework を削除します。このプロジェクトは置き換え済みです。 • Mobile SDK ライブラリとリソースの連動関係を SalesforceMobileSDK-iOS-Package repo から更新します。Mobile SDK 1.5 アプリケーションに、次のモジュールが新しく追加されました。 276 以前のリリースからの移行 Mobile SDK iOS アプリケーションを 1.5 から 2.0 に移行 する ◊ SalesforceHybridSDK (Dependencies/ フォルダにある) ◊ SalesforceOAuth (Dependencies/ フォルダにある) ◊ SalesforceSDKCore (Dependencies/ フォルダにある) ◊ SalesforceSDKResources.bundle (Dependencies/ フォルダにある) ◊ Cordova (Dependencies/Cordova/ フォルダにある) ◊ SalesforceCommonUtils (Dependencies/ThirdParty/SalesforceCommonUtils フォルダにある) ◊ openssl (Dependencies/ThirdParty/openssl フォルダにある libcrypto.a と libssl.a) ◊ sqlcipher (Dependencies/ThirdParty/sqlcipher フォルダにある) ◊ libxml2.dylib (システムライブラリ) • アプリケーションの www/ フォルダで、ハイブリッドの連動関係を更新します。 メモ: Visualforce アプリケーションを更新する場合は、bootconfig.js の変更のみが必要です。ハイ ブリッドアプリケーションでは、他のファイルは使用しません。 ◊ bootconfig.js 設定を新しい bootconfig.json 形式に移行します。 ◊ SalesforceOAuthPlugin.js、SFHybridApp.js、cordova.force.js、および forcetk.js を削除しま す。 ◊ SFTestRunnerPlugin.js、qunit.css、および qunit.js は、使用していなければ削除できます。 ◊ cordova.force.js (HybridShared/libs/ フォルダにある) を追加します。 ◊ ForceTK を使用している場合は、forcetk.mobilesdk.js (HybridShared/libs/ フォルダにある) を追加 します。 ◊ jQuery を使用している場合は、jQuery (HybridShared/external/ フォルダにある) を更新します。 ◊ SmartSync.js (HybridShared/libs/ フォルダにある) を追加します。 ◊ backbone-1.0.0.min.js と underscore-1.4.4.min.js (HybridShared/external/backbone/ フォル ダにある) を追加します。 ◊ jQuery (HybridShared/external/jquery/ フォルダにある) をまだ追加していない場合は、追加します。 ◊ 新しい SmartSync Data Framework を使用するには、次の操作を実行します。 - SmartSync.js (HybridShared/libs/ フォルダにある) を追加します。 - backbone-1.0.0.min.js と underscore-1.4.4.min.js (HybridShared/external/backbone/ フォ ルダにある) を追加します。 - • jQuery ( HybridShared/external/jquery/ フォルダにある) をまだ追加していない場合は、追加しま す。 AppDelegate を更新して、AppDelegate.h および AppDelegate.m ファイルを新しい設計パターンに適合し ます。AppDelegate クラスに変更を一切加えていない場合は、新しいテンプレートアプリケーションの AppDelegate.h および AppDelegate.m ファイルを古いファイルにコピーするだけで十分です。次の重要な ポイントを参考にしてください。 277 以前のリリースからの移行 Mobile SDK iOS アプリケーションを 1.5 から 2.0 に移行 する ◊ AppDelegate.h でのインストール手順は、次のとおりです。 - AppDelegate は SFContainerAppDelegate を継承しなくなりました。 - SFHybridViewController には新しい viewController プロパティがあります。 ◊ AppDelegate.m では、ブートストラップと認証フローの移動を AppDelegate で主に行うことが前提とな りました。これには、ユーザがログアウトしたりログインホストを切り替えたりするときの境界イベント の処理も含まれます。 278 第 17 章 リファレンス トピック: • • • • REST API リソース iOS アーキテクチャ Android アーキテクチャ Files API リファレンス リファレンスドキュメントは、GitHub で提供されています。 • • iOS: http://forcedotcom.github.com/SalesforceMobileSDK-iOS/ Documentation/SalesforceSDK/index.html Android: http://forcedotcom.github.com/SalesforceMobileSDK-Android/index.html 279 リファレンス REST API リソース REST API リソース Salesforce Mobile SDK を使用すると、ラッパーを作成することによって REST API の使用が簡略化されます。メ ソッドをコールし、正しいパラメータを指定するだけで十分です。残りの処理は自動的に行われます。次の表 に、使用可能なリソースとその用途を示します。詳細は、Force.com の REST API リソースページを参照してく ださい。 リソース URI 名 説明 Versions / バージョン、表示ラベル、および各バージョン のルートへのリンクなど、現在使用可能な各 Salesforce バージョンの概要情報をリストしま す。 Resources /vXX.X/ by Version リソース名および URI を含む、指定された API バージョンで使用可能なリソースをリストしま す。 Describe /vXX.X/sobjects/ Global 組織のデータで使用可能なオブジェクトとその メタデータをリストします。 sObject /vXX.X/sobjects/SObject/ Basic Information 指定されたオブジェクトの個別のメタデータを 説明します。特定のオブジェクトの新規レコー ドの作成にも使用できます。 SObject /vXX.X/sobjects/SObject/describe/ Describe 指定されたオブジェクトのすべてのレベルで、 個別のメタデータを完全に説明します。 sObject Rows /vXX.X/sobjects/SObject/id/ 指定されたオブジェクト ID に基づいてレコー ドにアクセスします。レコードを取得、更新、 または削除します。このリソースは、項目値の 取得にも使用できます。 sObject Rows by External ID /vXX.X/sobjects/SObjectName/fieldName/fieldValue 指定された外部 ID 項目の値に基づいて、新し いレコードを作成するか、既存のレコードを更 新 (レコードを Upsert) します。 sObject /vXX.X/sobjects/User/ユーザ ID/password User Password /vXX.X/sobjects/SelfServiceUser/セルフサービ ユーザパスワードを設定またはリセットした り、ユーザパスワードに関する情報を取得した りします。 Query /vXX.X/query/?q=soql 指定された SOQL クエリを実行します。 Search /vXX.X/search/?s=sosl 指定された SOSL 検索を実行します。検索文 字列は URL 符号化されている必要がありま す。 スユーザ ID/password 280 リファレンス iOS アーキテクチャ iOS アーキテクチャ ネイティブ SDK がコンシューマに提供する現在の機能の概要は、次のとおりです。 • OAuth 認証機能 • REST API 通信機能 • SmartStore によるアプリケーションデータの安全な保存と取得 メモ: SmartStore は現在、ネイティブテンプレートアプリケーションには公開されていませんが、バ イナリ配布には含まれています。 Salesforce ネイティブ SDK は基本的に 1 つのライブラリで、次のライブラリと連動関係があり、公開されていま す。 • libSalesforceNetworkSDK.a — REST API コールを容易にするための基礎となるライブラリ。このライブ ラリには、Mobile SDK GitHub リポジトリから使用できるサードパーティライブラリが必要です。「iOS プ ロジェクトの設定」を参照してください。 • libSalesforceOAuth.a — OAuth 認証を管理するための基礎となるライブラリ。 • libsqlite3.dylib — SQLite 機能へのアクセスを提供するライブラリ。これも、標準 iOS 開発環境の一部で す。 • fmdb — SQLite に対する Objective—C ラッパー。 メモ: このラッパーは現在、ネイティブテンプレートアプリケーションには公開されていませんが、 バイナリ配布には含まれています。 ネイティブ iOS オブジェクト 次のオブジェクトを使用して、ネイティブアプリケーションで Salesforce データにアクセスします。 • • • • SFRestAPI SFRestAPI (Blocks) SFRestRequest SFRestAPI (QueryBuilder) SFRestAPI SFRestAPI は、REST 要求を行うためのエントリポイントであり、通常、[SFRestAPI sharedInstance] を介 してシングルトンインスタンスとしてアクセスされます。 このオブジェクトから、次のような既定の多くの標準クエリを簡単に作成できます。 SFRestRequest* request = [[SFRestAPI sharedInstance] requestForUpdateWithObjectType:@"Contact" objectId:contactId fields:updatedFields]; 281 リファレンス Android アーキテクチャ 次のコマンドを使用して、要求を開始できます。 [[SFRestAPI sharedInstance] send:request delegate:self]; SFRestAPI (ブロック) SFRestAPI クラスのこのカテゴリ拡張を使用して、ブロックをコールバックメカニズムとして指定します。次に 例を示します。 NSMutableDictionary *fields = [NSMutableDictionary dictionaryWithObjectsAndKeys: @"John", @"FirstName", @"Doe", @"LastName", nil]; [[SFRestAPI sharedInstance] performCreateWithObjectType:@"Contact" fields:fields failBlock:^(NSError *e) { NSLog(@"Error: %@", e); } completeBlock:^(NSDictionary *d) { NSLog(@"ID value for object: %@", [d objectForKey:@"id"]); }]; SFRestRequest SFRestAPI で提供される標準 REST 要求だけでなく、直接 SFRestRequest メソッドを使用して独自の要求を作 成することもできます。 NSString *path = @"/v23.0"; SFRestRequest* request = [SFRestRequest requestWithMethod:SFRestMethodGET path:path queryParams:nil]; SFRestAPI (QueryBuilder) このカテゴリ拡張には、SOQL および SOSL のクエリ文字列を作成するためのユーティリティメソッドが備えら れています。例: NSString *soqlQuery = [SFRestAPI SOQLQueryWithFields:[NSArray arrayWithObjects:@"Id", @"Name", @"Company", @"Status", nil] sObject:@"Lead" where:nil limit:10]; NSString *soslQuery = [SFRestAPI SOSLSearchWithSearchTerm:@"all of these will be escaped:~{]" objectScope:[NSDictionary dictionaryWithObject:@"WHERE isactive=true ORDER BY lastname asc limit 5" forKey:@"User"]]; Android アーキテクチャ SalesforceSDK は、ライブラリプロジェクトとして提供されています。アプリケーションプロジェクトから SalesforceSDK プロジェクトを参照する必要があります。Android の開発者向けドキュメントを参照してくださ い。 282 リファレンス Android パッケージおよびクラス Android パッケージおよびクラス Android Mobile SDK の Java ソースファイルは、/src にあります。 パッケージカタログ パッケージ名 説明 com.salesforce.androidsdk.accounts ユーザアカウントを管理するためのクラス com.salesforce.androidsdk.app すべての Mobile SDK アプリケーションのエントリポイントクラスであ る SalesforceSDKManager が含まれています。このパッケージには、 内部で使用するアプリケーションユーティリティクラスもあります。 com.salesforce.androidsdk.auth 内部的にのみ使用されます。ログイン、OAuth 認証、HTTP アクセスを 処理します。 com.salesforce.androidsdk.phonegap ネイティブコードと Javascript コード間のブリッジを作成するためにハイ ブリッドアプリケーションで使用される内部クラス。Mobile SDK Javascript ライブラリを実装するプラグインが含まれています。SDK アプリケー ション内に独自の Javascript プラグインを実装する場合、ForcePlugin を拡張して、抽象 execute() 関数を実装します。「ForcePlugin クラス」 を参照してください。 com.salesforce.androidsdk.push このパッケージのコンポーネントは、Salesforce 転送通知の対象となるデ バイスを登録および登録解除します。次に、これらのコンポーネント は、Google Cloud Messaging (GCM) を通じて Salesforce 接続アプリケー ションから通知を受信します。「転送通知と Mobile SDK」を参照して ください。 com.salesforce.androidsdk.rest REST API アクティビティを処理するためのクラス。これらのクラスは Salesforce インスタンスとの通信を管理し、REST 要求の HTTP プロト コルを処理します。要求の送信に使用できる同期メソッドや非同期メ ソッドについての詳細は、ClientManager および RestClient を参照 してください。 com.salesforce.androidsdk.rest.files Files REST API の要求および応答を処理するためのクラス。 com.salesforce.androidsdk.security パスコードおよび暗号化を処理する内部クラス。独自のキーを提供して いる場合、Encryptor クラスを使用してハッシュを生成できます。 Encryptor を参照してください。 com.salesforce.androidsdk.smartstore SmartStore クラスとサポートクラス。 com.salesforce.androidsdk.ui アクティビティ (ログインアクティビティなど)。 com.salesforce.androidsdk.ui.sfhybrid ハイブリッドアプリケーションのアクティビティの基本クラス。 com.salesforce.androidsdk.ui.sfnative ネイティブアプリケーションのアクティビティの基本クラス。 com.salesforce.androidsdk.util ユーティリティおよびテストクラスが含まれています。これらのクラス の大部分は内部で使用されますが、いくつかの重要な例外もあります。 • TokenRevocationReceiver クラスのインスタンスを登録して、OAuth アクセストークンの取り消しを検出できます。 283 リファレンス パッケージ名 Android パッケージおよびクラス 説明 • EventObserver インターフェースを実装して、任意のイベントタイ プを傍受できます。 • EventsListenerQueue クラスは、独自のテストを実装する場合に便 利です。 • EventsObservable のソースコードを参照して、サポートされてい るすべてのイベントタイプのリストを確認できます。 com.salesforce.androidsdk.accounts クラス 説明 UserAccount Salesforce 組織に対して現在ログインしている単一のユー ザアカウントを表します。 UserAccountManager 現在ログインしているユーザアカウントにアクセスし たり、SmartStore を使用しないアプリケーションの新 しいアカウントを追加したりするために使用します。 UserAccountManagerWithSmartStore 現在ログインしているユーザアカウントにアクセスし たり、SmartStore を使用するアプリケーションの新し いアカウントを追加したりするために使用します。 com.salesforce.androidsdk.app クラス 説明 SalesforceSDKManager アプリケーションの抽象サブクラス。プロジェクトで 具象サブクラスを指定する必要があります。 UpgradeManager アップグレード用のヘルパークラス UUIDManager UUID 生成用のヘルパークラス com.salesforce.androidsdk.auth クラス 説明 AccountWatcher 設定アプリケーションからアカウントが削除された場 合にクリーンアップを担当するウォッチャ AuthenticatorService 認証を処理するサービス HttpAccess 汎用的な HTTP アクセスレイヤ LoginServerManager ログインホストを管理 OAuth2 一般的な OAuth2 要求のヘルパークラス 284 リファレンス Android パッケージおよびクラス com.salesforce.androidsdk.phonegap クラス 説明 ForcePlugin すべての Salesforce プラグインの抽象スーパークラス JavaScriptPluginVersion JavaScript コードから通知されたバージョンをカプセル 化するためのヘルパークラス SalesforceOAuthPlugin Salesforce OAuth の PhoneGap プラグイン SDKInfoPlugin SDK コンテナに関する情報を取得するための PhoneGap プラグイン SFAccountManagerPlugin ユーザアカウントを処理するための PhoneGap プラグ イン TestRunnerPlugin コンテナで JavaScript テストを実行するための PhoneGap プラグイン com.salesforce.androidsdk.push クラス 説明 PushBroadcastReceiver Google Cloud Messaging (GCM) からメッセージを受信 するクラス (内部使用) PushMessaging 転送通知用のデバイスの登録/登録解除を処理し、登録 情報を保存および取得するクラス (内部使用) PushNotificationInterface 転送通知を受信および処理するアプリケーションで実 装された公開インターフェース PushService Salesforce 組織から転送通知を受信するために Salesforce 接続アプリケーションでアプリケーションを登録/登録 解除するクラス (内部使用) com.salesforce.androidsdk.rest クラス 説明 AdminPrefsManager 接続アプリケーションの組織のシステム管理者によっ て行われたカスタム設定を表します。 ApiVersionStrings API バージョン情報をカプセル化します。 BootConfig 重要なアプリケーション設定値 (コンシューマ鍵、コー ルバック URI、OAuth 範囲、更新動作など) をカプセ ル化します。 ClientManager RestClient のファクトリ。必要に応じてログインフロー を起動します。 RestClient Force.com サーバとやり取りする認証クライアント RestRequest Force.com REST 要求ラッパー RestResponse REST 応答ラッパー 285 リファレンス Android パッケージおよびクラス com.salesforce.androidsdk.rest.files クラス 説明 ApiRequests REST 要求を作成するためのヘルパーメソッド ConnectUriBuilder ユーザ ID と省略可能なパラメータの特別な処理を行っ て、Connect URI を作成します。 FileRequests Connect API を使用する、ファイルの HTTP 要求を定 義します。 RenditionType サーバでサポートされる変換タイプの列挙子 com.salesforce.androidsdk.security Google の PRNG の最新の修正が含まれます。 クラス 説明 Encryptor 暗号化/復号化/ハッシュ計算用のヘルパークラス PRNGFixes 非活動状態タイムアウトマネージャ。必要に応じてパ スコード画面を起動します。 PasscodeManager 非活動状態タイムアウトマネージャ。必要に応じてパ スコード画面を起動します。 com.salesforce.androidsdk.smartstore.app このパッケージは、SmartStore ライブラリプロジェクトの一部です。 クラス 説明 SalesforceSDKManagerWithSmartStore SmartStore を使用するすべての強制アプリケーション のスーパークラス (SmartStore ライブラリプロジェクト に存在する) UpgradeManagerWithSmartStore SmartStore を使用するアプリケーションのアップグレー ドマネージャ (SmartStore ライブラリプロジェクトに存 在する) com.salesforce.androidsdk.smartstore.phonegap このパッケージは、SmartStore ライブラリプロジェクトの一部です。 クラス 説明 SmartStorePlugin SmartStore の PhoneGap プラグイン StoreCursor クエリカーソルを表す com.salesforce.androidsdk.smartstore.store このパッケージは、SmartStore ライブラリプロジェクトの一部です。 286 リファレンス Android パッケージおよびクラス クラス 説明 DBHelper SmartStore の基盤となるデータベースにアクセスする ヘルパークラス DBOpenHelper 通常のデータベース作成とバージョン設定を行うため のヘルパークラス IndexSpec インデックス指定を表す QuerySpec クエリ指定を表す SmartSqlHelper SmartSql の解析および実行用のヘルパークラス SmartStore JSON ドキュメントの検索可能で安全なストア com.salesforce.androidsdk.ui クラス 説明 AccountSwitcherActivity 認証されたアカウント間の切り替えや新しいアカウン トの追加のためのカスタムダイアログ。このダイアロ グは、アカウントが切り替わった後に、アクティビティ スタックから取り出されます。 CustomServerUrlEditor 異なるログインホストをユーザが選択できるカスタム ダイアログ LoginActivity ログイン画面 ManageSpaceActivity ユーザがユーザデータをクリアしたり、ログアウトし たりできるようにする、上書き可能なアクティビティ。 OAuthWebviewHelper OAuth ログインプロセスを行う Web ビューインスタン スを管理するためのヘルパークラス PasscodeActivity パスコード (PIN) 画面 SalesforceAccountRadioButton Salesforce アカウントを表すカスタムラジオボタン。こ のラジオボタンにテキストを表示するには、カスタム setText() メソッドを使用します。 SalesforceR SDK 外で定義されたリソースの参照を許可するクラス SalesforceServerRadioButton カスタムサーバエンドポイントを表すカスタムラジオ ボタン。このラジオボタンにテキストを表示するには、 カスタム setText() メソッドを使用します。 ServerPickerActivity OAuth フロー中にログインサーバ URL を変更するため のアクティビティ。ユーザはカスタムサーバを追加し たり、サーバのリストから選択したりできます。 287 リファレンス Android パッケージおよびクラス com.salesforce.androidsdk.ui.sfhybrid クラス 説明 SalesforceDroidGapActivity Cordova ベースのアプリケーションのメインアクティビ ティを定義する SalesforceGapViewClient Cordova ベースのアプリケーションの Web ビュークラ イアントを定義する com.salesforce.androidsdk.ui.sfnative 重要: ネイティブ Mobile SDK アプリケーションの各アクティビティで、このパッケージのいずれかのクラスの 機能を拡張または複製する必要があります。 クラス 説明 SalesforceActivity Android Activity クラスに基づいたネイティブアプリ ケーションのメインアクティビティ。 SalesforceListActivity Android ListActivity クラスに基づいたネイティブア プリケーションのメインアクティビティ。 SalesforceExpandableListActivity Android ExpandableListActivity クラスに基づいた ネイティブアプリケーションのメインアクティビティ。 com.salesforce.androidsdk.util クラス 説明 EventsListenerQueue 特定のイベントが発生するまでテストを待機できるよ うにするため、キューを使用してアクティビティイベ ントを追跡するクラス EventsObservable SDK で生成されたイベントの登録および取得に使用 (主 にテストで使用) EventsObserver SDK イベントのオブザーバー ForceAppInstrumentationTestCase Salesforce Mobile SDK を使用したアプリケーションのテ スト用のスーパークラス HybridInstrumentationTestCase ハイブリッドアプリケーションのテスト用のスーパー クラス JSTestCase JavaScript 内でテストを実行するためのスーパークラス JUnitReportTestRunner 実行時間制限を使用してテストを実行するテストラン ナー LogUtil ログ記録用のヘルパーメソッド NativeInstrumentationTestCase ネイティブアプリケーションのテスト用のスーパーク ラス 288 リファレンス ライブラリ クラス 説明 TimeLimitedTestRunner テスト実行の有効期間を制限するテストランナー TokenRevocationReceiver アクセストークンの取り消しイベントのリスナー UriFragmentParser クエリ文字列スタイルを使用してパラメータを渡す URI フラグメントを解析します (foo=bar&bar=foo2 など)。 UserSwitchReceiver ユーザの切り替えイベントのリスナー ライブラリ ライブラリは /libs にあります。 ライブラリ名 説明 android-junit-report-1.2.6.jar Ant JUnit タスクの XML フォーマッタによって作成されるレポー トと同様の形式の XML テストレポートを作成する Android 用の カスタム計測テストランナー apache-mime4j-0.6.jar Java ストリームに基づく MIME メッセージパーサー armeabi/*.so ARM ベースのデバイスで sqlcipher に必要なネイティブライブラ リ (**) commons-code.jar, guava-r09.jar sqlcipher に必要な Java ライブラリ cordova-2.3.0.jar ハイブリッドアプリケーションで使用されるオープンソースのモ バイル開発フレームワーク (*) httpmime-4.0.3.jar MIME でコード化されたエンティティ sqlcipher.jar データベースファイルの透過的な 256 ビット AES 暗号化を行う SQLite のオープンソースの拡張機能 (**) volley_android-4.2.2_r2.jar Google の Android ネットワーキングライブラリ x86/*.so Intel ベースのデバイスで sqlcipher に必要なネイティブライブラ リ (*) は、ハイブリッドアプリケーションに必要なファイルを示します。 (**) は、SmartStore に必要なファイルを示します。 Android リソース リソースは /res にあります。 289 リファレンス Android リソース drawable-hdpi ファイル 使用 sf__edit_icon.png サーバピッカー画面 sf__highlight_glare.png ログイン画面 sf__hybrid__icon.png ハイブリッドアプリケーションアイコン sf__icon.png ネイティブアプリケーションアイコン drawable-ldpi ファイル 使途 sf__hybrid__icon.png ハイブリッドアプリケーションアイコン sf__icon.png アプリケーションアイコン drawable-mdpi ファイル 使途 sf__edit_icon.png サーバピッカー画面 sf__highlight_glare.png ログイン画面 sf__hybrid__icon.png ハイブリッドアプリケーションアイコン sf__ic_refresh_sync_anim0.png アプリケーションアイコン sf__icon.png アプリケーションアイコン drawable ファイル 使途 sf__header_bg.png ログイン画面 sf__progress_spinner.xml ログイン画面 sf__toolbar_background.xml ログイン画面 drawable-xhdpi ファイル 使途 sf__hybrid__icon.png ハイブリッドアプリケーションアイコン sf__icon.png ネイティブアプリケーションアイコン 290 リファレンス Android リソース 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 ログイン画面 (タブレット) sf__progress_spinner.xml ログイン画面 (タブレット) sf__refresh_loader.png ログイン画面 (タブレット) sf__toolbar_background.xml ログイン画面 (タブレット) drawable-xlarge-port ファイル 使途 sf__oauth_background.png ログイン画面 (タブレット) drawable-xxhdpi ファイル 使途 sf__hybrid__icon.png ハイブリッドアプリケーションアイコン sf__icon.png ネイティブアプリケーションアイコン layout ファイル 使途 sf__account_switcher.xml アカウントの切り替え画面 sf__custom_server_url.xml サーバピッカー画面 sf__login.xml ログイン画面 sf__manage_space.xml ユーザがアプリケーションデータをクリアしたり、ロ グアウトしたりできる画面 sf__passcode.xml PIN 画面 291 リファレンス Android リソース ファイル 使途 sf__server_picker.xml サーバピッカー画面 (廃止) sf__server_picker_list.xml サーバピッカー画面 layout-land ファイル 使途 sf__passcode.xml PIN 画面 layout-xlarge ファイル 使途 sf__header_bottom.xml ヘッダー (タブレット) sf__header_separator.xml ヘッダー (タブレット) sf__login.xml ログイン画面 (タブレット) sf__login_header.xml ログイン画面 (タブレット) sf__passcode.xml PIN 画面 (タブレット) sf__server_picker.xml サーバピッカー画面 (タブレット) sf__server_picker_header.xml サーバピッカー画面 (タブレット) menu ファイル 使途 sf__clear_custom_url.xml [接続を追加] ダイアログ sf__login.xml ログインメニュー (電話) values ファイル 使途 bootconfig.xml 接続アプリケーションの構成設定 sf__colors.xml 色 sf__dimens.xml Dimensions sf__strings.xml SDK 文字列 sf__style.xml スタイル strings.xml その他の文字列 (アプリケーション名) 292 リファレンス Files API リファレンス values-xlarge ファイル 使途 sf__colors.xml 色 (タブレット) sf__dimens.xml サイズ (タブレット) sf__styles.xml スタイル (タブレット) xml ファイル 使途 authenticator.xml アプリケーションで使用するアカウントの設定 config.xml PhoneGap のプラグイン設定ファイル。ハイブリッドに 必要です。 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) を参照してください。 ownedFilesList 指定されたユーザが所有するファイルのリストを取得する要求を生成します。結果の 1 ページを返します。 署名 public static RestRequest ownedFilesList(String userId, Integer pageNum); パラメータ 名前 型 説明 userId String ユーザの ID。null の場合、コンテキスト (ログイン) ユー ザの ID が使用されます。 pageNum Integer 取得する結果のページの開始値 0 のインデックス。null の 場合、最初のページを取得します。 293 リファレンス FileRequests メソッド (Android) 例 RestRequest request = FileRequests.ownedFilesList(null, null); filesInUsersGroups 指定されたユーザの所属グループが所有するファイルのリストを取得する要求を生成します。 署名 public static RestRequest filesInUsersGroups(String userId, Integer pageNum); パラメータ 名前 データ型 説明 userId String ユーザの ID。null の場合、コンテキスト (ログイン) ユー ザの ID が使用されます。 pageNum Integer 取得する結果のページの開始値 0 のインデックス。null の 場合、最初のページを取得します。 例 RestRequest request = FileRequests.filesInUsersGroups(null, null); filesSharedWithUser 指定されたユーザと共有されたファイルのリストを取得する要求を生成します。 署名 public static RestRequest filesSharedWithUser(String userId, Integer pageNum); パラメータ 名前 データ型 説明 userId String ユーザの ID。null の場合、コンテキスト (ログイン) ユー ザの ID が使用されます。 pageNum Integer 取得する結果のページの開始値 0 のインデックス。null の 場合、最初のページを取得します。 294 リファレンス FileRequests メソッド (Android) 例 RestRequest request = FileRequests.filesSharedWithUser(null, null); fileDetails 特定のバージョンのファイルの詳細を取得できる要求を生成します。 署名 public static RestRequest fileDetails(String sfdcId, String version); パラメータ 名前 データ型 説明 sfdcId String ファイルの ID。null の場合、IllegalArgumentException が発生します。 version String 取得するバージョン。null の場合、最新バージョンを取得 します。 例 String id = <some_file_id>; RestRequest request = FileRequests.fileDetails(id, null); batchFileDetails 複数のファイルの詳細を取得できる要求を生成します。 署名 public static RestRequest batchFileDetails(List sfdcIds); パラメータ 名前 データ型 説明 sfdcIds List 1 つ以上のファイルの ID のリスト。リストの ID がひとつ でも null の場合、IllegalArgumentException が発生し ます。 295 リファレンス FileRequests メソッド (Android) 例 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); パラメータ 名前 データ型 説明 sfdcId String 表示されるファイルの ID。null の場合、 IllegalArgumentException が発生します。 version String 取得するバージョン。null の場合、最新バージョンを取得 します。 renditionType RenditionType 返される変換の種別を指定します。使用できる値は次のと おりです。 • PDF • FLASH • SLIDE • THUMB120BY90 • THUMB240BY180 • THUMB720BY480 null の場合、THUMB120BY90 が使用されます。 pageNum Integer 取得するページの開始値 0 のインデックス。null の場合、 最初のページを取得します。 例 String id = <some_file_id>; RestRequest request = FileRequests.fileRendition(id, null, "PDF", 0); fileContents 指定されたファイルのバイナリコンテンツを取得できる要求を生成します。 296 リファレンス FileRequests メソッド (Android) 署名 public static RestRequest fileContents(String sfdcId, String version); パラメータ 名前 データ型 説明 sfdcId String 表示されるファイルの ID。null の場合、 IllegalArgumentException が発生します。 version String 取得するバージョン。null の場合、最新バージョンを取得 します。 例 String id = <some_file_id>; RestRequest request = FileRequests.fileContents(id, null); fileShares 指定されたファイルを共有するエンティティのリストからページを取得できる要求を生成します。 署名 public static RestRequest fileShares(String sfdcId, Integer pageNum); パラメータ 名前 データ型 説明 sfdcId String 表示されるファイルの ID。null の場合、 IllegalArgumentException が発生します。 pageNum Integer 取得する結果のページの開始値 0 のインデックス。null の 場合、最初のページを取得します。 例 String id = <some_file_id>; RestRequest request = FileRequests.fileShares(id, null); addFileShare 指定されたエンティティと指定のファイルを共有できる要求を生成します。 297 リファレンス FileRequests メソッド (Android) 署名 public static RestRequest addFileShare(String fileId, String entityId, String shareType); パラメータ 名前 データ型 説明 fileId String 共有されるファイルの ID。null の場合、 IllegalArgumentException が発生します。 entityID String ファイルを共有するユーザまたはグループの ID。null の 場合、IllegalArgumentException が発生します。 shareType String 共有種別。有効な値は「V」(表示) と「C」(コラボレー ション) です。 例 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); パラメータ 名前 データ型 説明 shareId String 削除されるファイル共有の ID。null の場合、 IllegalArgumentException が発生します。 例 String id = <some_fileShare_id>; RestRequest request = FileRequests.deleteFileShare(id); 298 リファレンス SFRestAPI (Files) カテゴリ — 要求メソッド (iOS) uploadFile ローカルファイルをサーバにアップロードできる要求を生成します。この要求により、バージョン 1 のファイル がサーバで作成されます。 署名 public static RestRequest uploadFile(File theFile, String name, String description, String mimeType) throws UnsupportedEncodingException; パラメータ 名前 データ型 説明 theFile File サーバにアップロードされるローカルファイルのパス。 name String ファイルの名前。 description String ファイルの説明。 mimeType String ファイルの MIME タイプ (タイプがわかっている場合)。 それ以外の場合は null。 発生する例外 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 ページを返します。 299 リファレンス SFRestAPI (Files) カテゴリ — 要求メソッド (iOS) 署名 - (SFRestRequest *) requestForOwnedFilesList:(NSString *)userId page:(NSUInteger)page; パラメータ 名前 データ型 説明 userId NSString * ユーザの ID。nil の場合、コンテキスト (ログイン) ユーザ の ID が使用されます。 page NSUInteger 取得するページの開始値 0 のインデックス。nil の場合、 最初のページを取得します。 例 SFRestRequest *request = [[SFRestAPI sharedInstance] requestForOwnedFilesList:nil page:0]; requestForFilesInUsersGroups:page: 指定されたユーザの所属グループが所有するファイルのリストを取得する要求を生成します。 署名 - (SFRestRequest *) requestForFilesInUsersGroups:(NSString *)userId page:(NSUInteger)page; パラメータ 名前 データ型 説明 userId NSString * ユーザの ID。nil の場合、コンテキスト (ログイン) ユーザ の ID が使用されます。 page NSUInteger 取得するページの開始値 0 のインデックス。nil の場合、 最初のページを取得します。 例 SFRestRequest *request = [[SFRestAPI sharedInstance] requestForFilesInUsersGroups:nil page:0]; 300 リファレンス SFRestAPI (Files) カテゴリ — 要求メソッド (iOS) requestForFilesSharedWithUser:page: 指定されたユーザと共有されたファイルのリストを取得する要求を生成します。 署名 - (SFRestRequest *) requestForFilesSharedWithUser:(NSString *)userId page:(NSUInteger)page; パラメータ 名前 データ型 説明 userId NSString * ユーザの ID。nil の場合、コンテキスト (ログイン) ユーザ の ID が使用されます。 page NSUInteger 取得するページの開始値 0 のインデックス。nil の場合、 最初のページを取得します。 例 SFRestRequest *request = [[SFRestAPI sharedInstance] requestForFilesSharedWithUser:nil page:0]; requestForFileDetails:forVersion: 特定のバージョンのファイルの詳細を取得できる要求を生成します。 署名 - (SFRestRequest *) requestForFileDetails:(NSString *)sfdcId forVersion:(NSString *)version; パラメータ 名前 データ型 説明 sfdcId NSString * ファイルの ID。nil の場合、要求が失敗します。 version NSString * 取得するバージョン。nil の場合、最新バージョンを取得 します。 例 NSString *id = [NSString stringWithString:@"some_file_id"]; SFRestRequest *request = 301 リファレンス SFRestAPI (Files) カテゴリ — 要求メソッド (iOS) [[SFRestAPI sharedInstance] requestForFileDetails:id forVersion:nil]; requestForBatchFileDetails: 複数のファイルの詳細を取得できる要求を生成します。 署名 - (SFRestRequest *) requestForBatchFileDetails:(NSArray *)sfdcIds; パラメータ 名前 データ型 説明 sfdcIds NSArray * 1 つ以上のファイルの ID の配列。ID は文字列として表さ れます。 例 NSArray *ids = [NSArray arrayWithObject:@"id1",@"id2",...,nil]; SFRestRequest *request = [[SFRestAPI sharedInstance] requestForBatchFileDetails:ids]; requestForFileRendition:version:renditionType:page: 指定されたファイルのページの表示されたプレビューを取得できる要求を生成します。 署名 - (SFRestRequest *) requestForFileRendition:(NSString *)sfdcId version:(NSString *)version renditionType:(NSString *)renditionType page:(NSUInteger)page; パラメータ 名前 データ型 説明 sfdcId NSString * 表示されるファイルの ID。nil の場合、要求が失敗しま す。 version NSString * 取得するバージョン。nil の場合、最新バージョンを取得 します。 302 リファレンス SFRestAPI (Files) カテゴリ — 要求メソッド (iOS) 名前 データ型 説明 renditionType NSString * 返される変換の種別を指定します。使用できる値は次のと おりです。 • "PDF" • "FLASH" • "SLIDE" • "THUMB120BY90" • "THUMB240BY180" • "THUMB720BY480" nil の場合、THUMB120BY90 が使用されます。 page NSUInteger 取得するページの開始値 0 のインデックス。nil の場合、 最初のページを取得します。 例 NSString *id = [NSString stringWithString:@"some_file_id"]; SFRestRequest *request = [[SFRestAPI sharedInstance] requestForFileRendition:id version:nil renditionType:nil page:nil]; requestForFileContents:version: 指定されたファイルのバイナリコンテンツを取得できる要求を生成します。 署名 - (SFRestRequest *) requestForFileContents:(NSString *) sfdcId version:(NSString*) version; パラメータ 名前 データ型 説明 sfdcId NSString * 表示されるファイルの ID。nil の場合、要求が失敗しま す。 version NSString * 取得するバージョン。nil の場合、最新バージョンを取得 します。 例 NSString *id = [NSString stringWithString:@"some_file_id"]; SFRestRequest *request = 303 リファレンス SFRestAPI (Files) カテゴリ — 要求メソッド (iOS) [[SFRestAPI sharedInstance] requestForFileContents:id version:nil]; requestForFileShares:page: 指定されたファイルを共有するエンティティのリストからページを取得できる要求を生成します。 署名 - (SFRestRequest *) requestForFileShares:(NSString *)sfdcId page:(NSUInteger)page; パラメータ 名前 データ型 説明 sfdcId NSString * 表示されるファイルの ID。nil の場合、要求が失敗しま す。 page NSUInteger 取得するページの開始値 0 のインデックス。nil の場合、 最初のページを取得します。 例 NSString *id = [NSString stringWithString:@"some_file_id"]; SFRestRequest *request = [[SFRestAPI sharedInstance] requestForFileShares:id page:nil]; requestForAddFileShare:entityId:shareType: メソッド 指定されたエンティティと指定のファイルを共有できる要求を生成します。 署名 - (SFRestRequest *) requestForAddFileShare:(NSString *)fileId entityId:(NSString *)entityId shareType:(NSString*)shareType; パラメータ 名前 データ型 説明 fileId NSString * 共有されるファイルの ID。nil の場合、要求が失敗しま す。 304 リファレンス SFRestAPI (Files) カテゴリ — 要求メソッド (iOS) 名前 データ型 説明 entityId NSString * ファイルを共有するユーザまたはグループの ID。nil の場 合、要求が失敗します。 shareType NSString * 共有種別。有効な値は「V」(表示) と「C」(コラボレー ション) です。 例 NSString *id = [NSString stringWithString:@"some_file_id"]; NSString *entId = [NSString stringWithString:@"some_entity_id"]; SFRestRequest *request = [[SFRestAPI sharedInstance] requestForAddFileShare:id entityId:entId shareType:@"V"]; requestForDeleteFileShare: 指定されたファイル共有を削除できる要求を生成します。 署名 - (SFRestRequest *) requestForDeleteFileShare:(NSString *)shareId; パラメータ 名前 データ型 説明 shareId NSString * 削除されるファイル共有の ID。nil の場合、要求が失敗し ます。 例 NSString *id = [NSString stringWithString:@"some_fileshare_id"]; SFRestRequest *request = [[SFRestAPI sharedInstance] requestForDeleteFileShare:id]; requestForUploadFile:name:description:mimeType: メソッド ローカルファイルをサーバにアップロードできる要求を生成します。この要求により、バージョン 1 の新しい ファイルがサーバで作成されます。 署名 - (SFRestRequest *) requestForUploadFile:(NSData *)data 305 リファレンス ハイブリッドアプリケーションの Files メソッド name:(NSString *)name description:(NSString *)description mimeType:(NSString *)mimeType; パラメータ 名前 データ型 説明 data NSData * サーバにアップロードするデータ。 name NSString * ファイルの名前。 description NSString * ファイルの説明。 mimeType NSString * ファイルの MIME タイプ (タイプがわかっている場合)。 それ以外の場合は、nil。 例 NSData *data = [NSData dataWithContentsOfFile:@"/Users/JayVee/Documents/mypic.png"]; 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 メソッド 指定されたユーザが所有するファイルのリストからページを返します。 306 リファレンス ハイブリッドアプリケーションの Files メソッド 署名 forcetk.Client.prototype. ownedFilesList = function(userId, page, callback, error) パラメータ 名前 説明 userId 既存のユーザの ID。null の場合、コンテキスト (現在ログインしている) ユー ザの ID が使用されます。 page 取得する結果のページの開始値 0 のインデックス。null の場合、最初のペー ジを取得します。 callback サーバ応答を非同期で受信して処理する関数。 error サーバエラーを処理する関数。 例 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) パラメータ 名前 説明 userId 既存のユーザの ID。null の場合、コンテキスト (現在ログインしている) ユー ザの ID が使用されます。 page 取得する結果のページの開始値 0 のインデックス。null の場合、最初のペー ジを取得します。 callback サーバ応答を非同期で受信して処理する関数。 error サーバエラーを処理する関数。 307 リファレンス ハイブリッドアプリケーションの Files メソッド 例 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) パラメータ 名前 説明 userId 既存のユーザの ID。null の場合、コンテキスト (現在ログインしている) ユー ザの ID が使用されます。 page 取得する結果のページの開始値 0 のインデックス。null の場合、最初のペー ジを取得します。 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) 308 リファレンス ハイブリッドアプリケーションの Files メソッド パラメータ 名前 説明 sfdcId 既存のファイルの ID。null の場合、エラーが返されます。 version 取得するバージョン。null の場合、最新バージョンを取得します。 callback サーバ応答を非同期で受信して処理する関数。 error サーバエラーを処理する関数。 例 ftkclient.fileDetails(id, null, function(response){ /* do something with the returned JSON data */}, function(error){ alert("Error!");} ); batchFileDetails メソッド 複数のファイルの詳細を返します。 署名 forcetk.Client.prototype. batchFileDetails = function(fileIds, callback, error) パラメータ 名前 説明 fileIds 1 つ以上の既存のファイルの ID のリスト。リストの ID がひとつでも null の 場合、エラーが返されます。 callback サーバ応答を非同期で受信して処理する関数。 error サーバエラーを処理する関数。 例 ftkclient.batchFileDetails(ids, function(response){ /* do something with the returned JSON data */}, function(error){ alert("Error!");} ); 309 リファレンス ハイブリッドアプリケーションの Files メソッド fileRenditionPath メソッド service/data を基準とするファイル変換の相対パスを返します。HTML (img タグなど) では、代わりにベア ラートークン URL を使用します。 署名 forcetk.Client.prototype. fileRenditionPath = function(fileId, version, renditionType, page) パラメータ 名前 説明 fileId 表示される既存のファイルの ID。null の場合、エラーが返されます。 version 取得するバージョン。null の場合、最新バージョンを取得します。 renditionType 返される変換の種別を指定します。使用できる値は次のとおりです。 • PDF • FLASH • SLIDE • THUMB120BY90 • THUMB240BY180 • THUMB720BY480 null の場合、THUMB120BY90 が使用されます。 page 取得するページの開始値 0 のインデックス。null の場合、最初のページを取 得します。 例 ftkclient.fileRenditionPath(id, null, "THUMB240BY180", null); fileContentsPath メソッド service/data を基準とするファイルコンテンツの相対パスを返します。html (img タグなど) では、代わりにベ アラートークン URL を使用します。 署名 forcetk.Client.prototype. fileContentsPath = function(fileId, version) 310 リファレンス ハイブリッドアプリケーションの Files メソッド パラメータ 名前 説明 fileId 表示される既存のファイルの ID。null の場合、エラーが返されます。 version 取得するバージョン。null の場合、最新バージョンを取得します。 例 ftkclient.fileContentsPath(id, null); fileShares メソッド このファイルを共有するエンティティのリストからページを返します。 署名 forcetk.Client.prototype. fileShares = function (fileId, page, callback, error) パラメータ 名前 説明 fileId 表示される既存のファイルの ID。null の場合、エラーが返されます。 page 取得する結果のページの開始値 0 のインデックス。null の場合、最初のペー ジを取得します。 callback サーバ応答を非同期で受信して処理する関数。 error サーバエラーを処理する関数。 例 ftkclient.fileShares(id, null, function(response){ /* do something with the returned JSON data */}, function(error){ alert("Error!");} ); addFileShare メソッド 指定されたファイル ID のファイル共有を指定されたエンティティ ID に追加します。 311 リファレンス ハイブリッドアプリケーションの Files メソッド 署名 forcetk.Client.prototype. addFileShare = function (fileId, entityId, shareType, callback, error) パラメータ 名前 説明 fileId 共有される既存のファイルの ID。null の場合、IllegalArgumentException が発生します。 entityID ファイルを共有する既存のユーザまたはグループの ID。null の場合、 IllegalArgumentException が発生します。 shareType 共有種別。有効な値は「V」(表示) と「C」(コラボレーション) です。 callback サーバ応答を非同期で受信して処理する関数。 error サーバエラーを処理する関数。 例 ftkclient.addFileShare(id, null, "V", function(response){ /* do something with the returned JSON data */}, function(error){ alert("Error!");} ); deleteFileShare メソッド 指定されたファイル共有を削除します。 署名 forcetk.Client.prototype. deleteFileShare = function(sharedId, callback, error) パラメータ 名前 説明 shareId 削除される既存のファイル共有の ID。null の場合、 IllegalArgumentException が発生します。 callback サーバ応答を非同期で受信して処理する関数。 error サーバエラーを処理する関数。 312 リファレンス ハイブリッドアプリケーションの Files メソッド 例 ftkclient.deleteFileShare(id, function(response){ /* do something with the returned JSON data */}, function(error){ alert("Error!");} ); 313