LoginSignup
20
8

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-07-27

さぁ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ページはこちらから

20
8
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
8