Edited at

Alexa ディスプレイ端末対応時にセッションをクローズする時の注意点

More than 1 year has passed since last update.

さぁEcho Spotも日本で発売されて、更に盛り上がってきたAlexa界隈!(個人の感じ方によります。)

直近で、ハマって一度リジェクトされたので、備忘録的に残しておきます。

※ask-sdk v2 for node.jsを利用しています


セッションの継続判定


index.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での設定に地味に変わっています。


alexa-sdk_v1

this.response.shouldEndSession(bool);



ask-sdk_v2

return handlerInput.responseBuilder

.speak('hogehoge')
.withShouldEndSession(bool)
.getResponse();

まぁここまでは、ドキュメントそのままやん。ワロスワロス。

ドキュメント読めやというマサカリ飛んできそうですが...


StopIntent , CancelIntent時にはホーム画面へすぐに遷移させる必要がある

この条件がクリア出来ない場合は、リジェクト対象になります。

今回リジェクトの理由としては、以前からStopIntentとCancelIntent時に挨拶的な返答を用意していたため、それを画面上でも表示しようとしたことが原因だと思われます。


EndIntentRequest.js

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の開発者や勉強会が少ないので、ぜひ増えてほしいこの頃です。

Eventページはこちらから