[iOS 10] SiriKit サンプルアプリ(UnicornChat)を動かしてみた(その1)

この記事は公開されてから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 プロジェクト

プロジェクトを開くと次のようになっています。

001

(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'

201

定義がAnyObjectからAnyに変わっているので修正します。

202

(2) Type 'UCSendMessageIntentHandler' dose not conform to protocol 'INSendMessageIntentHandling'

203

INSendMessageIntentHandlingプロトコルのメソッドが変わっているため、必須メソッドが定義されていない状態になっています。

204

上のコードを下のように修正します。

205

handle(sendMessage:completion:)メソッドに@escapingを追加するだけで、エラーは無くなりますが、INSendMessageIntentHandlingプロトコルでは、オプショナルなメソッドも、同じように変更されていますので、全メソッドのブロック部分を修正しないと動作できません。

(3) 'Init' has been renamed to 'init(describing:)'

206

Stringのイニシャライザが変更されているので、下記のように修正します。

207

4 コンパイル・実行

Siriから呼び出されて動作するは、SiriExtensionなので、スキーマーを変更します。

002

SiriExtensionは、エクステンションなので、Runすると、アプリケーションの選択ダイアログが表示されますので、ここでSiriを選択します。

003

プログラムを実行[Run]するとSiriが起動します。

004-2 004

「ユニコーンチャットでメッセージ送って」と話しかけると、Siriが認識した文字が画面に表示されて、「私が"UnicornChat”のデータにアクセスする必要があります」と答えが返ってきます。

この時点で既に、Siriが、私の話しかけた内容をメッセージドメインであると認識しており、また、メッセージドメインで動作できるUnicornChatというアプリが存在することを知っています。

ここでは、「Siri設定」をタップして遷移するAppサポートのページで、UnicornChatのスイッチをONにします。

005 006

ユーザ許可を得た時点で、再び、「ユニコーンチャットでメッセージ送って」と話しかけると、今度は、UnicornChatのUIが表示されて、「わかりました・・・メッセージに書く内容と宛先を教えてください。」と返事が帰ってきます。

この時点でResolveフェーズに入っています。 現時点では、宛先とメッセージ内容がパラメータとして不足しているので、Siriは、それを要求してきています。

007

「おはよう」と話しかけると「メッセージを作成しました」と表示され、「送信」ボタンが表示されています。(サンプルでは、宛先が無くてもこの確認画面に進みます)

この時点で、UnicornChatは、必要なパラメータが揃った事をSiriに伝えたので、Siriが、最後のComfirmフェーズに入ります。 そして。confirm(sendMessage:completion:)メソッドで.successが返されたので、ユーザに最後のアクションを求めています。

008

ここで「送信して」と話しかけるか、または「送信」ボタンを押すと、「メッセージを送信しました」となります。 「送信」というユーザのアクションがあった時点で、Handleフェーズに入っています。実際には、handle(sendMessage:completion:)メソッドに入って、実施の送信動作を行います。サンプルでは、送信が成功したことをhandle(sendMessage:completion:)で返すために、Siriは「送信しました。」と表示したわけです。

なお、サンプルアプリでは、宛先は指定されていなくてもよく、また、実際の送信は行われず、必ず成功となります。

009

5 ユーザの許可

最初、「私が"UnicornChat”のデータにアクセスする必要が有ります」という返事とともに誘導されたのが、設定 > Siri > Appサポートのページです。

010 011

Siriで作成した拡張機能を有効にするには、ユーザの許可が必要です。

ドキュメントでは、INPreferences.requestSiriAuthorizationや、Info.plistのNSSiriUsageDescription使用して、Siriからの使用を許可するアラートを表示させる要領が説明されていますが、UnicornChatのサンプルには、これに関するコードは有りませんでした。

6 info.plist

インテント拡張のアプリは、自分がどの種類のドメインの、どの種類のインテントに対応しているかをSiriに伝えるためにInfo.plistを使用しています。 そして、そのキーは、NSExtension > NSExtensionAttributesの下に置かれるIntentsSupported及び、IntentsRestrictedWhileLockedです。

下記は、SiriExtentionSiriUIExtentionのinfo.plistの内容です。

012 013

(1) IntentsSupported

IntentsSupportedキーは、必須であり、サポートするIntentクラス名を設定します。 サンプルでは、SiriExtensionSiriUIExtesion の両方にINSendMessageIntentが設定されています。

ここに指定されているINSendMessageIntentは、Messagingドメインのインテントです。


参考: Intents Domains

インテントは、複数設定できますが、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