[iOS 10] SiriKit サンプルアプリ(UnicornChat)を動かしてみた(その1)
1 はじめに
iOS10の新機能であるSiriKitを使用すると、サードパーティーのアプリからでもSiriを使うことができます。
今回は、Appleで公開されているSiriKitのサンプル(UnicornChat)を実行してみて、SiriKitの実装について概観してみました。
UnicornChat: Extending Your Apps with SiriKit
2016/09/14現在、上記のサンプルアプリは削除されています。(この他の多くのサンプルも、GM版公開時点で削除されています) 本記事は、削除される前(2016/08/01)のものを使用しております。 新しい、サンプルコードが公開されましたら、それを元に本記事は修正される予定です。
本記事の内容は、少し量が多くなったため、前後段に分けて書かせていただきました。後段の記事は、下記になります。
[iOS 10] SiriKit サンプルアプリ(UnicornChat)を動かしてみた(その2)
2 プロジェクト
プロジェクトを開くと次のようになっています。
(1) UnicornChat
アプリの本体です。 SiriKitは、Extensionとして作成されるため、その元となるアプリですが、サンプルでは、ただの白い画面が出るだけで、何も実装されていません。
(2) SiriExtension
インテント拡張の本体です。SiriKitとのやり取りである、Resolve、Confirm、Handleの各フェースは、ここで、それぞれのメソッドとして定義されています。
(3) SiriUIExtension
インテント拡張のUI部分です。 UnicornChatでは、独自のUIをSiriに表示するために使用されています。
(4) Framework
Frameworkの中には、UnicornChat及び、IntentsUI.Frameworkの次の2つが入っています。 UnicornChatの方は、このアプリ(ユニコーンチャット)自体の機能実装であり、SiriKitとは、まったく関係ありません。 一方、IntentsUI.Frameworkは、インテント拡張のフレームワークです。
3 Swiftの更新によるエラー
(1) Use of undeclared type 'AnyObject'
定義がAnyObjectからAnyに変わっているので修正します。
(2) Type 'UCSendMessageIntentHandler' dose not conform to protocol 'INSendMessageIntentHandling'
INSendMessageIntentHandlingプロトコルのメソッドが変わっているため、必須メソッドが定義されていない状態になっています。
上のコードを下のように修正します。
handle(sendMessage:completion:)メソッドに@escapingを追加するだけで、エラーは無くなりますが、INSendMessageIntentHandlingプロトコルでは、オプショナルなメソッドも、同じように変更されていますので、全メソッドのブロック部分を修正しないと動作できません。
(3) 'Init' has been renamed to 'init(describing:)'
Stringのイニシャライザが変更されているので、下記のように修正します。
4 コンパイル・実行
Siriから呼び出されて動作するは、SiriExtensionなので、スキーマーを変更します。
SiriExtensionは、エクステンションなので、Runすると、アプリケーションの選択ダイアログが表示されますので、ここでSiriを選択します。
プログラムを実行[Run]するとSiriが起動します。
「ユニコーンチャットでメッセージ送って」と話しかけると、Siriが認識した文字が画面に表示されて、「私が"UnicornChat”のデータにアクセスする必要があります」と答えが返ってきます。
この時点で既に、Siriが、私の話しかけた内容をメッセージドメインであると認識しており、また、メッセージドメインで動作できるUnicornChatというアプリが存在することを知っています。
ここでは、「Siri設定」をタップして遷移するAppサポートのページで、UnicornChatのスイッチをONにします。
ユーザ許可を得た時点で、再び、「ユニコーンチャットでメッセージ送って」と話しかけると、今度は、UnicornChatのUIが表示されて、「わかりました・・・メッセージに書く内容と宛先を教えてください。」と返事が帰ってきます。
この時点でResolveフェーズに入っています。 現時点では、宛先とメッセージ内容がパラメータとして不足しているので、Siriは、それを要求してきています。
「おはよう」と話しかけると「メッセージを作成しました」と表示され、「送信」ボタンが表示されています。(サンプルでは、宛先が無くてもこの確認画面に進みます)
この時点で、UnicornChatは、必要なパラメータが揃った事をSiriに伝えたので、Siriが、最後のComfirmフェーズに入ります。 そして。confirm(sendMessage:completion:)メソッドで.successが返されたので、ユーザに最後のアクションを求めています。
ここで「送信して」と話しかけるか、または「送信」ボタンを押すと、「メッセージを送信しました」となります。 「送信」というユーザのアクションがあった時点で、Handleフェーズに入っています。実際には、handle(sendMessage:completion:)メソッドに入って、実施の送信動作を行います。サンプルでは、送信が成功したことをhandle(sendMessage:completion:)で返すために、Siriは「送信しました。」と表示したわけです。
なお、サンプルアプリでは、宛先は指定されていなくてもよく、また、実際の送信は行われず、必ず成功となります。
5 ユーザの許可
最初、「私が"UnicornChat”のデータにアクセスする必要が有ります」という返事とともに誘導されたのが、設定 > Siri > Appサポートのページです。
Siriで作成した拡張機能を有効にするには、ユーザの許可が必要です。
ドキュメントでは、INPreferences.requestSiriAuthorizationや、Info.plistのNSSiriUsageDescription使用して、Siriからの使用を許可するアラートを表示させる要領が説明されていますが、UnicornChatのサンプルには、これに関するコードは有りませんでした。
6 info.plist
インテント拡張のアプリは、自分がどの種類のドメインの、どの種類のインテントに対応しているかをSiriに伝えるためにInfo.plistを使用しています。 そして、そのキーは、NSExtension > NSExtensionAttributesの下に置かれるIntentsSupported及び、IntentsRestrictedWhileLockedです。
下記は、SiriExtentionとSiriUIExtentionのinfo.plistの内容です。
(1) IntentsSupported
IntentsSupportedキーは、必須であり、サポートするIntentクラス名を設定します。 サンプルでは、SiriExtension と SiriUIExtesion の両方にINSendMessageIntentが設定されています。
ここに指定されているINSendMessageIntentは、Messagingドメインのインテントです。
インテントは、複数設定できますが、info.plistの上の方が優先です。また、ユーザの音声が複数のIntentにヒットするような曖昧さが生じた場合も、上から優先してヒットすることになります。
(2) IntentsRestrictedWhileLocked
IntentsRestrictedWhileLockedキーはオプションです。ここに記載あれば、デバイスがロック状態の時にも動作させることができます。 サンプルでは、SiriExtensionの方のだけINSendMessageIntentが設定されていました。
参考: Creating the Intents Extension
7 最後に
今回は、SiriKitのサンプルであるUnicornChatを動作させて見て、実装の要領を概観してみました。
引き続き、後段の記事で更に内容を確認してみましたので、ぜひ、ご参照ください。
[iOS 10] SiriKit サンプルアプリ(UnicornChat)を動かしてみた(その2)
8 参考リンク
Siri + Apps
SiriKit Programming Guide
Introducing SiriKit
Extending Your Apps with SiriKit