Integrate Amazon Lex With Flutter App
Tags: flutter, aws, tutorial
Published: 2021-09-01 14:21:33

For industries and companies to maintain an advantage over their competitors, better customer service offers in their mobile apps are crucial. So it is equally important to understand how to integrate a bot in a flutter app. As Amazon is increasing its share in the development of flutter apps with its Amplify service, now integration of Amazon lex with flutter has become easier than ever. 

At this moment, Amplify supports Authentication, Storage, and Analytics for Flutter. 

We will communicate with Lex by using a REST API.


### What we are going to use💻?
We will be creating a chat with the bot and will be using some amazing packages from  [flutter pub](https://pub.dev/)  to make our work efficient and easier.
To start, we need to install the following packages:
<ul>
<li> <a href="https://pub.dev/packages/http">http 0.13.3</a>  : To send request to Amazon Lex</li>
<li> <a href="https://pub.dev/packages/sigv4">sigv4 5.0.0</a>  : To authenticate the service </li>
<li> <a href="https://pub.dev/packages/uuid">uuid 3.0.4</a>  : To create unique uuid </li>
<li> <a href="https://pub.dev/packages/flutter_chat_ui">flutter_chat_ui 1.1.9</a> : To create basic chat UI</li>
</ul>

Now our vision is crystal clear and ready to start our project.
![Ready gif](https://media.giphy.com/media/h7dboNZPsoGwRg9bid/giphy.gif)

## Lets' Start
Normally, I set up the backend first, then connect the frontend. Hopefully, you have successfully set up Amazon Lex in AWS.
![Let Start ](https://media.giphy.com/media/2uIlaHVsql55CLP3as/giphy.gif)

### 1. Setup Backend File
I have created a file named `bot_service.dart` which will contain the code to interact with our lex bot.

```
import 'dart:convert';
import 'dart:developer';

import 'package:amazon_cognito_identity_dart_2/sig_v4.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:sigv4/sigv4.dart';

class BotService {
  Map<String,dynamic> result;
  String botName= "<NAME_OF_BOT>";
  String kAccessKeyId = '<ACCESS_KEY>';
  String kSecretAccessKey = '<SECRET_ACCESS_KEY>';
  String botAlias= "<BOT_ALIAS>";
  String botAWSRegion= "<AWS_LEX_REGION>";
 

  Future<Map<String,dynamic>> callBot(String message) async {
    var response;
    String requestUrl= "https://runtime.lex."+botAWSRegion+".amazonaws.com/bot/"+botName+"/alias/"+botAlias+"/user/1234/text";

    Sigv4Client client = Sigv4Client(
      region: botAWSRegion,
      serviceName: 'lex',
      defaultContentType: 'application/json; charset=utf-8',
      keyId: kAccessKeyId,
      accessKey: kSecretAccessKey,
    );

    final request = client.request(
     requestUrl,
      method: 'POST',
      body: jsonEncode({'inputText': message}),
    );
    
    response = await http.post(request.url,
        headers: request.headers, body: request.body);
    result = jsonDecode(response.body);
    return result;
  }
}
```

Take special care while inserting the required values and region of the Amazon Lex Bot.

In `<ACCESS_KEY>` and `<SECRET_ACCESS_KEY>` you have to insert the value of your Amazon role's secret or you can create a new role for the bot and permit it to call Amazon Lambda Functions(I would prefer to go with creating a new role for the bot).


### 2. Create Chat UI
To create the chat UI, I will use `flutter_chat_ui` package as it provides a lot of already built features like handling messages and a chat message model.

```
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:flutter_chat_ui/flutter_chat_ui.dart';
import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
import 'package:uuid/uuid.dart';

import './bot_service.dart';

class BotScreen extends StatefulWidget {
  const BotScreen({Key? key}) : super(key: key);

  @override
  _BotScreenState createState() => _BotScreenState();
}

class _BotScreenState extends State<BotScreen> {
  List<types.Message> messages=[];
  final _user = const types.User(id: '1234556');
  final _bot = const types.User(id: "123");
//id of bot and user doesn't matter here as we have only pair interaction

  BotService _botService = BotService();

  @override
  void initState() {
    super.initState();
    _loadMessages();
  }

  void _addMessage(types.Message message) async {
    setState(() {
      messages.insert(0, message);
    });
    log("${message.toJson()["text"]}");
    var data = await _botService.callBot(message.toJson()["text"]);
    log("#####${data['message']}");
    setState(() {
      messages.insert(0, botMessageReply(data['message']));
    });
  }

  types.Message botMessageReply(String message) {
    return types.TextMessage(
      author: _bot,
      createdAt: DateTime.now().millisecondsSinceEpoch,
      id: const Uuid().v4(),
      text: message,
    );
  }

  void _handleSendPressed(types.PartialText message) {
    final textMessage = types.TextMessage(
      author: _user,
      createdAt: DateTime.now().millisecondsSinceEpoch,
      id: const Uuid().v4(),
      text: message.text,
    );
    _addMessage(textMessage);
  }

  void _loadMessages() async {
    List<types.Message> messagesList = [];
    Future.delayed(Duration(milliseconds: 300), () {
      messagesList.add(types.TextMessage(
        author: _bot,
        createdAt: DateTime.now().millisecondsSinceEpoch,
        id: const Uuid().v4(),
        text: "Hello. My name is TUTU- your bot. How can I help you?",
      ));

      setState(() {
        messages = messagesList;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar:AppBar(automaticallyImplyLeading: false,title:Text("BOT"),backgroundColor:Colors.purpleAccent),
      body: Chat(
        messages: messages,
        showUserNames: true,
        onSendPressed: _handleSendPressed,
        user: _user,
      ),
    );
  }
}


```

<ul>
<li>`_loadMessages() Function`: This function load messages from the firebase/local file. Here I am pushing a starting message which will be instantiated by the bot when user opens this bot.</li>
<li>`_addMessage() Function`: This function interacts with bot_service.dart which further interacts with LEX API to get the result of the message sent by the user.
</li>
</ul>



### 3. Here is Our Final Product🔥🔥

| BOT Screen  |
| --- | ----------- |
|<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628683299915/dxuvYO3nNj.png" width="500" height="100" /> | <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628683300948/W-k8ktDWS.png" width="100" height="100" /> |



## Congratulations🎉
![Congratulations GIF](https://media.giphy.com/media/l49JNZ87F3AmPoH0A/giphy.gif)
Great job, you've connected your Flutter app to the Lex bot... well done! <br>
Please let me know if you have any questions or concerns regarding this article and I will do my best to help or learn more.