さぁEcho Spotも日本で発売されて、更に盛り上がってきたAlexa界隈!(個人の感じ方によります。)
直近で、ハマって一度リジェクトされたので、備忘録的に残しておきます。
※ask-sdk v2 for node.jsを利用しています
#セッションの継続判定
const hogehogeIntentRequest = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return (request.type === 'IntentRequest' && request.intent.name === 'AMAZON.HogeHoge');
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak('ほげほげ') //インテントが呼び出された直後に発話される内容
.reprompt('何か問いかけてみてください') //ユーザーからの反応がない場合に発話される内容
.getResponse();
}
}
一般的な、Handlerの定義だと上記の様になると思います。
Amazon EchoやEcho dotなどのディスプレイが無いデバイスの場合、repromptの設定の有無によってセッションの継続判定フラグであるShouldEndSessionの値が自動的に判定されていました。
- reprompt有りの場合...セッションが継続される (ShouldEndSessionがfalseの扱い)
- repromptなしの場合...セッションが終了される (ShouldEndSessionがtrueの扱い)
#ディスプレイ付き端末で、テンプレートを表示した場合
公式のテンプレートリファレンスはこちらから
shouldEndSessionアトリビュートおよびセッションタイムアウトの使用に記載されていますが、ディスプレイ付きのEcho端末向けにテンプレートを表示し、画面上で表示したテンプレートがアクティブな場合、セッションは開かれたままになります。
要は、shouldEndSessionの動作を明確にするためにセッションを終了させる場合はtrue、セッションを継続させる場合は、falseを指定してあげる必要があります。
#shouldEndSessionに値を設定する
ここでまたask-sdkv2の罠が...
this.response.shouldEndSessionからhandlerInput.responseBuilder.withShouldEndSessionでの設定に地味に変わっています。
this.response.shouldEndSession(bool);
return handlerInput.responseBuilder
.speak('hogehoge')
.withShouldEndSession(bool)
.getResponse();
まぁここまでは、ドキュメントそのままやん。ワロスワロス。
ドキュメント読めやというマサカリ飛んできそうですが...
#StopIntent , CancelIntent時にはホーム画面へすぐに遷移させる必要がある
この条件がクリア出来ない場合は、リジェクト対象になります。
今回リジェクトの理由としては、以前からStopIntentとCancelIntent時に挨拶的な返答を用意していたため、それを画面上でも表示しようとしたことが原因だと思われます。
const EndIntentRequest = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return (request.type === 'IntentRequest' && request.intent.name === 'AMAZON.HogeHoge');
},
handle(handlerInput) {
const response.responseBuilder;
response.speak('ばいばいー');
response.withShouldEndSession(true); //意図的に終了させる
//ディスプレイ端末の判定フラグを取得
const displayFlg = util.displayDeviceCheck(handlerInput);
const iconPath = 'https://hogehogehoge/hoge.png'
//ディスプレイ端末である場合は、テンプレートを付与します
if (displayFlg) {
const iconImg = new alexa.ImageHelper()
.addImageInstance(displayIconPath)
.getImage();
response.addRenderTemplateDirective({
type: 'BodyTemplate7',
backButton: 'VISIBLE',
title: 'また来てね!',
image: iconImg,
token: 'TOKEN'
})
}
return response.getResponse();
}
}
上記のようにStop,Cancelインテント時に呼び出されるHandlerがあったとします。
終了時にディスプレイ付き端末の場合、何らかの画像と「また来てね!」という表示をさせるような内容になっています。
Stop,Cancelインテント用のHandlerで、この後にセッションが継続されることはないため、ShouldEndSessionの値は明示的にtrueとし、セッションを終了させるようにしています。
この場合、当初意図した動きとしては、読み上げ中のみテンプレートが表示され、読み上げ完了後にテンプレートがすぐに閉じられるものだと考えていました。
実際は、テンプレートが端末の画面上でアクティブであるため、ShouldEndSessionをtrueにして明示的にセッションを終了させようとしていても、セッション継続扱いとされてしまい、30秒間テンプレートが画面上に表示され続けてしまいます。
このことから、下記の特定の条件の場合、ストア申請時にリジェクトを受ける場合があります。
- ディスプレイ付きのEcho端末向けのSkillで、Stop,CancelIntentHandlerのShouldEndSessionに明示的にtrueを渡していない。
- やり取りの中で、テンプレートが1度でも表示されるSkillの場合は、セッション終了にまつわるHandler全てで、 ShouldEndSessionにtrueを渡す必要があります。
- Stop,CancelIntentHandlerで、テンプレートを表示するSkill
- Stop,CancelIntentはすぐにSkillを閉じる必要があるため、テンプレートを表示すること出来ないようです。
結局の所、Stop,CancelIntent時は、何もせずShouldEndSessionにtrue渡すことを忘れないようにすることが大切そうです。
#最後に
Alexa開発者になりませんか?
今ならSkill公開するだけで、Tシャツもらえます。
そして30日間のユニークユーザーが100人超えただけで、Echo Dotがもらえるこの太っ腹!
Alexaの開発者や勉強会が少ないので、ぜひ増えてほしいこの頃です。