JavaでAlexaスキルをつくってみた 

# 環境準備

EclipseからAWS Lambdaを利用するためのプラグインのインストール
↓にキレイにまとめて下さっているので、こちらを参考に導入して下さい。
[AWS Toolkit for Eclipse - ヤマムギ]
(https://www.yamamanx.com/aws-toolkit-eclipse/)

# おおまかな流れ
1. Alexa開発者ポータルでスキルを作成する
    - スキル名を決める
    - スキルモデルを選択する
    - スキルの呼び出し名を決める
    - インテントを追加する（必要に応じてインテントスロットを作成）
    - モデルを保存してビルドする
2. Alexaスキルの脳となるLambdaファンクションを作成する
    - GitHubからサンプルスキルをEclipseにクローン
    - Eclipse上でプロジェクトをインポート
    - Alexa開発者ポータルで作成したインテント用にソースを書き換える
    - AWS上にLambdaファンクションをアップロード
    - LambdaからAlexaスキルの紐付けをする
3. AlexaスキルからLambdaファンクションへの紐付けをする
4. テスト実施

# Alexaスキルの作成
> まずは、[Amazon 開発者ポータル]
(https://developer.amazon.com/ja/)にアクセスして、Alexaスキル作成画面に移動します。

![スクリーンショット 2018-05-31 23.40.04.png](https://qiita-image-store.s3.amazonaws.com/0/255347/d5969413-aa91-a0af-5746-d43af48d3a49.png)

![スクリーンショット 2018-05-31 23.40.25.png](https://qiita-image-store.s3.amazonaws.com/0/255347/b28c7b80-9818-9816-a21e-957b06c560f7.png)
![スクリーンショット 2018-05-31 23.40.49.png](https://qiita-image-store.s3.amazonaws.com/0/255347/9ddb7de7-6261-0578-fb9b-8232251b9e7d.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/255347/2cee15d8-8b30-49af-5567-e8eb2e2b9390.png)

> スキル名を決めます。
言語は日本語にしておいてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/255347/7caf573c-2afd-e6a6-1082-a2886cf134d6.png)

> 今回はカスタムスキルを選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/255347/b7644bb6-4034-c9f8-4382-29083f9cdcde.png)

> 呼び出し名を決めます。
「Alexa、**〇〇**を開いて」や、「**〇〇**で△△して」の、**”〇〇”**の部分になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/255347/ceafad3a-9a8c-8983-ffc1-4aabd6f20bc6.png)

> インテントを作ります。「〇〇で**△△**して」の**”△△”**の部分に相当します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/255347/f0ad58a1-a8e0-9b08-ea85-5683fa9b4d18.png)

> とりあえず**「HelloIntent」**というインテントを作りました。

![d8d9499b6ff2b28c5488cf0243e66221.png](https://qiita-image-store.s3.amazonaws.com/0/255347/a8315f94-ffb5-d810-1c24-94e2b84774fc.png)

> 次はHelloIntentに対して発話例を設定していきますが、
インテントスロットも使ってみようと思うので、**「Location」**というインテントスロットを設定して、
Amazonの標準スロット**AMAZON.City**を使ってみようと思います。
**{Location}**には、Amazonで既に登録されている一般的な地名が入ります。
多分大阪市もあるでしょう。知らんけど。

![de046866c6b159c335d2ee183c9118d0.png](https://qiita-image-store.s3.amazonaws.com/0/255347/54c47539-08b4-bad5-db4c-e18bd7995a4d.png)

> 後はサンプル発話のところに、さっき作ったインテントスロットを絡めて、
ユーザが言いそうな発話例をいくつか登録します。
ある程度登録し終わったら、**「モデルを保存」**と**「モデルをビルド」**を押します。
ビルドが正常に終了したら、Alexa管理者ポータルの作業は一旦ここで中断です。

# Lambdaファンクションの作成
> 今回は最初にインストールしたAWS Toolkit for Eclipseを使って、
EclipseからLambdaファンクションを作成します。

> GitHubのJavaサンプルプロジェクトを利用するので、[ここ]
(https://github.com/alexa/skill-samples-java)からEclipseにクローンします。
クローンが終わりましたら、helloworldプロジェクトだけインポートし、HelloWorldSpeechlet.javaを編集します。

```java:HelloWorldSpeechlet.java(49行目)

    @Override
    public SpeechletResponse onIntent(SpeechletRequestEnvelope<IntentRequest> requestEnvelope) {
        IntentRequest request = requestEnvelope.getRequest();
        log.info("onIntent requestId={}, sessionId={}", request.getRequestId(),
                requestEnvelope.getSession().getSessionId());
        // リクエストからインテントを取得します
        Intent intent = request.getIntent();
        String intentName = (intent != null) ? intent.getName() : null;
        // インテントからスロットの値を取得します
        Slot slot = intent.getSlot("Location");
        String slotValue = slot.getValue();

        if ("HelloIntent".equals(intentName)) {
            // スロットの値を引数に渡すように変更します
            return getHelloResponse(slotValue);
        } else if ("AMAZON.HelpIntent".equals(intentName)) {
            return getHelpResponse();
        } else {
            return getAskResponse("HelloWorld", "This is unsupported.  Please try something else.");
        }
    }
```
```java:HelloWorldSpeechlet.java(93行目)
 private SpeechletResponse getHelloResponse(String slotValue) {

       String speechText = null;
       if(slotValue != null && slotValue.contains("大阪")) {
       // スロットの値に"大阪"が含まれる場合
           speechText = "おっす、儲かりまっか？";
       } else {
       // それ以外の場合
           speechText = "こんにちは、お元気ですか？";
       }
       // Create the Simple card content.
       SimpleCard card = getSimpleCard("HelloWorld", speechText);

       // Create the plain text output.
       PlainTextOutputSpeech speech = getPlainTextOutputSpeech(speechText);

       return SpeechletResponse.newTellResponse(speech, card);
   }
```
# AWSにLambdaファンクションをアップロード
> EclipseのプロジェクトエクスプローラのHelloWorldSpeechlet.javaを右クリックして、Amazon Web サービスから**「Upload Function to AWS Lambda」**を選択します。
（Windowsの場合はhelloworldプロジェクトを右クリックで表示されます。）
![d3c3474569fca6c150038ca66131edf4.png](https://qiita-image-store.s3.amazonaws.com/0/255347/ac3cd1b0-d2a6-9dbd-3200-5af09748d8a2.png)

> S3バケットやロールを選択してそのまま画面を進めていくと、Lambdaファンクションのアップロードが完了します。

# LambdaファンクションからAlexaスキルを紐付けする
![0293130e647ab290557dfb07e844b017.png](https://qiita-image-store.s3.amazonaws.com/0/255347/793e8e29-7278-7e7a-59e8-9d2ccd230b54.png)

> AWSコンソールのLambdaの管理画面で、先ほどアップロードしたLambdaを選択して、
「トリガーの追加」でAlexa Skills Kitを選択します。
すると画面下に、Alexa SkillのスキルIDを指定するフォームが出てきます。

> Alexa開発者ポータルの画面に戻り、
エンドポイントのメニューの中にある「amzn1.ask.skill.」から始まる**スキルID**をコピーしてきて貼り付けます。
最後に右上の「保存」を押して終わりです。

# AlexaスキルからLambdaファンクションを紐付けする
![3bbe8b050fef15a338b89bd90c5c7bb0.png](https://qiita-image-store.s3.amazonaws.com/0/255347/846b70b0-427e-0d9c-77ac-12e2c5ffa96c.png)
> 次は逆に、Lambdaファンクションの管理画面の一番右上にある「arn:aws:lambda:」から始まるARNを、
Alexa管理者ポータルのエンドポイントメニューの**「デフォルトの地域」**のフォームに貼り付けます。
こちらも最後に**「エンドポイントを保存」**を押して準備完了です。

# 実際にテストで動かしてみる
![e6206ad13a96d39351f8665750bca0b2.png](https://qiita-image-store.s3.amazonaws.com/0/255347/d5bc7308-b055-e583-3c5d-aa5802062b04.png)

> Alexa管理者ポータルの**「テスト」**メニューに移動し、
「サンプルスキルで大阪のあいさつをして」と入力してみます。
Alexaが「おっす、儲かりまっか？」と答えてくれたら成功です！

お疲れ様でした！