Using Huawei Cloud Functions as Chatbot Service in Flutter ChatBotApp Part-2
Tags: huaweiaccountkit, cloudfunctions, appgalleryconnect, dart
Published: 2022-05-05 06:13:13

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/04kcm7m93cas7kg0kiij.png)
**Introduction**

In this article, we will learn how to use Huawei Cloud Functions service as Chatbot service in ChatBotApp in flutter. Cloud Functions enables serverless computing.
It provides the Function as a Service (FaaS) capabilities to simplify app development and O&M by splitting service logic into functions and offers the Cloud Functions SDK that works with Cloud DB and Cloud Storage so that your app functions can be implemented more easily. Cloud Functions automatically scales in or out functions based on actual traffic, freeing you from server resource management and helping you reduce costs.

**Key Functions**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3jqaxk1914h2mqncrv3.png)
**Key Concepts** 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rxgvvlfmjrja7l5zxzl1.png)
**How the Service Works**
To use Cloud Functions, you need to develop cloud functions that can implement certain service functions in AppGallery Connect and add triggers for them, for example, HTTP triggers for HTTP requests, and Cloud DB triggers for data deletion or insertion requests after Cloud DB is integrated. After your app that integrates the Cloud Functions SDK meets conditions of specific function triggers, your app can call the cloud functions, which greatly facilitates service function building.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/crdiui4jage3q60t41i8.png)
**Platform Support** 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ek9oin3io0e140vx7rxn.png)
**Development Overview**
You need to install Flutter and Dart plugin in IDE and I assume that you have prior knowledge about the Flutter and Dart.
**Hardware Requirements**
A computer (desktop or laptop) running Windows 10.
Android phone (with the USB cable), which is used for debugging.
**Software Requirements**
- Java JDK 1.7 or later.
- Android studio software or Visual Studio or Code installed.
- HMS Core (APK) 4.X or later.
**Integration process**
**Step 1:** Create Flutter project. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sy16l0zu18x7ut8tmsvz.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l55cb3sddxkl790nv5vb.png)
Step 2: Add the App level gradle dependencies. Choose inside project Android > app > build.gradle.
`apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
`
Root level gradle dependencies
`maven {url 'https://developer.huawei.com/repo/'}
classpath 'com.huawei.agconnect:agcp:1.5.2.300'`  

Step 3: Add the below permissions in Android Manifest file.
`<uses-permission android:name="android.permission.INTERNET" />`

Step 4: Add downloaded file into parent directory of the project. Declare plugin path in pubspec.yaml file under dependencies.

Add path location for asset image.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s74kyisirjgvy2bucsdp.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/026k4uelhfgsiq2zvikj.png)
**Prevoius article**  
 [Using Huawei Cloud Functions as Chatbot Service in Flutter ChatBotApp Part-1](https://forums.developer.huawei.com/forumPortal/en/topic/0202860006325440216)

**Let's start coding**

**main.dart**

```
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ChatBotService',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'ChatBotService'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool isLoggedIn = false;
  String str = 'Login required';
  final HMSAnalytics _hmsAnalytics = new HMSAnalytics();

  List<String> gridItems = ['Email Service', 'Call Center', 'FAQ', 'Chat Now'];

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child:  
            Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Visibility(
              visible: true,
              child: Card(
                child: Padding(
                  padding: EdgeInsets.all(20),
                  child: Text(
                    str,
                    style: const TextStyle(color: Colors.teal, fontSize: 22),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (!isLoggedIn) {
            setState(() {
              isLoggedIn = true;
              signInWithHuaweiID();
            });
            print('$isLoggedIn');
          } else {
            setState(() {
              isLoggedIn = false;
              signOutWithID();
            });
            print('$isLoggedIn');
          }
        },
        tooltip: 'Login/Logout',
        child: isLoggedIn ? const Icon(Icons.logout) : const Icon(Icons.login),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  void signInWithHuaweiID() async {
    try {
      // The sign-in is successful, and the user's ID information and authorization code are obtained.
      Future<AuthAccount> account = AccountAuthService.signIn();
      account.then(
        (value) => setLoginSuccess(value),
      );
    } on Exception catch (e) {
      print(e.toString());
    }
  }

  Future<void> _enableLog() async {
    _hmsAnalytics.setUserId("ChatBotServiceApp");
    await _hmsAnalytics.enableLog();
  }

  void setLoginSuccess(AuthAccount value) {

    setState(() {
      str = 'Welcome ' + value.displayName.toString();
    });
    showToast(value.displayName.toString());
    print('Login Success');

  }

  Future<void> signOutWithID() async {
    try {
      final bool result = await AccountAuthService.signOut();
      if (result) {
        setState(() {
          str = 'Login required';
          showToast('You are logged out.');
        });
      }
    } on Exception catch (e) {
      print(e.toString());
    }
  }

  Future<void> showToast(String name) async {
    Fluttertoast.showToast(
        msg: "$name",
        toastLength: Toast.LENGTH_SHORT,
        gravity: ToastGravity.CENTER,
        timeInSecForIosWeb: 1,
        backgroundColor: Colors.lightBlue,
        textColor: Colors.white,
        fontSize: 16.0);
  }
}

```
**ChatPage.dart**
```
class ChatPage extends StatefulWidget {
  const ChatPage({Key? key}) : super(key: key);

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

class _ChatPageState extends State<ChatPage> {
  List<types.Message> _messages = [];
  final _user = const types.User(id: '06c33e8b-e835-4736-80f4-63f44b66666c');
  final _bot = const types.User(id: '06c33e8b-e835-4736-80f4-63f54b66666c');

  void _addMessage(types.Message message) {
    setState(() {
      _messages.insert(0, 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);
    callCloudFunction2(message.text);
  }

  void _loadMessages() async {
    final response = await rootBundle.loadString('assets/messages.json');
    final messages = (jsonDecode(response) as List)
        .map((e) => types.Message.fromJson(e as Map<String, dynamic>))
        .toList();

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Chat(
        messages: _messages,
        onAttachmentPressed: null,  
        onMessageTap: null,
        onPreviewDataFetched: null,
        onSendPressed: _handleSendPressed,
        user: _user,
      ),
    );
  }

  Future<void> callCloudFunction2(String msg) async {
    try {
      RequestData data = RequestData(msg);
      List<Map<String, Object>> params = <Map<String, Object>>[data.toMap()];
      var input = data.toMap();
      FunctionCallable functionCallable =
          FunctionCallable('test-funnel-\$latest');
      FunctionResult functionResult = await functionCallable.call(input);
      print("Input " + input.toString());
      var result = functionResult.getValue();
      final textMessage = types.TextMessage(
        author: _bot,
        createdAt: DateTime.now().millisecondsSinceEpoch,
        id: const Uuid().v4(),
        text: jsonDecode(result)['response'].toString(),
      );
      _addMessage(textMessage);
    } on PlatformException catch (e) {
      print(e.message);
    }
  }
}

```
**handler.js**
 

```
let myHandler = function(event, context, callback, logger) {
    try {
        var _body = JSON.parse(event.body);
        var reqData = _body.message;
		var test = '';
        if(reqData == '1'){
        test = "Thank you for choosing, you will get callback in 10 min.";
    }else if(reqData == '2'){
         test = "Please click on the link https://feedback.com/myfeedback";
    }else if(reqData == '3'){
         test = "Please click on the link https://huawei.com/faq";
    }
    else if(reqData == 'Hi'){
        test =  " Welcome to ChatBot Service.";
    }else{
        test = "Enter 1. For call back. 2. For send feedback. 3. For FAQ ";
    }
        let res = new context.HTTPResponse({"response": test}, {
        "res-type": "simple example", 
        "faas-content-type": "json"
        }, "application/json", "200");
       logger.info("Response : "+JSON.stringify(res));
        callback(res);
    } catch (error) {
        let res = new context.HTTPResponse({"response": error}, {
        "res-type": "simple example", 
        "faas-content-type": "json"
        }, "application/json", "300");
        callback(res);
    }

    
};

module.exports.myHandler = myHandler;
```
**Result**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ncpovm4ahpfzv5x8k5jx.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ui05g3nrq78q67xw0n9e.png)
**Tricks and Tips**

Makes sure that agconnect-services.json file added.
Make sure dependencies are added yaml file.
Run flutter pug get after adding dependencies.
Make sure that service is enabled in agc.
Makes sure images are defined in yaml file.
**Conclusion**
In this article, we have learnt how to integrate Huawei Account kit, analytics kit and ChatBot function using Cloud Functions in flutter ChatBotApp. Once Account kit integrated, users can login quickly and conveniently sign in to apps with their Huawei IDs after granting initial access permission.
Thank you so much for reading. I hope this article helps you to understand the integration of Huawei Account kit, Analytics kit and Huawei Cloud Functions in flutter ChatBotApp.

**Reference**

[Cloud Functions](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-cloudfunction-introduction-0000001059279544)
[Training Videos](https://developer.huawei.com/consumer/en/training/course/video/C101641296521420104)   
[Checkout in forum](https://forums.developer.huawei.com/forumPortal/en/topic/0201866007643970019)