Hello world Google Home
Github Actions — building first agent for Google Assistant in Java
Some time ago I published unofficial Google Actions SDK written in Java. Source code and documentation can be found on Github: Google-Actions-Java-SDK. Library can be also downloaded from Bintray jCenter:
The goal for this project is to give Android/Java developers possibility to build solutions for Google Home without learning new language (official Actions SDK is written in Node.js).
Google Assistant Action from scratch
In this post we’ll go through Google Assistant agent implementation. We’ll build simple Github client which will tell us what is the one of the hottest repositories from last days.
Source code for final project can be found here: Github Google Actions
Environment configuration
Our Github Actions agent will be built in Java and hosted on App Engine.
At the beginning we need to create new project in Google Cloud Platform dashboard.
When it’s done remember your project ID, it will be needed during configuration. In example described in this post id is: *githubactions*.
Then we need to install CLIs for Google Cloud and Google Actions:
Project init
Now let’s create our Java/gradle project (I use IntelliJ IDEA, free community edition). For better code structure, I also created module app. Final structure looks like this (some files/tries aren’t show for better readability):
When it’s done, run $ gactions init
from /app
directory. It should create example config file: app/actions.json
:
This config file defines our agent’s Actions. It’s mostly self-describing but in case you would like to know better what is happening here, please visit official documentation.
Now let’s update it with our configuration. We would like to have an agent which is able to handle two actions/intents:
-
assistant.intent.action.MAIN (defined in Google Actions SDK)
Action is launched when user starts talking, but without clear intention e.g.: “Ok Google, talk to Github”. In most cases this should be used as an agent introduction. -
com.frogermcs.githubactions.intent.TRENDING (defined by us)
In response to this request, our agent will find one of the hottest repositories from last days. There are a couple utterances which should fire this intent:
“Ok Google, ask Github what are the hottest repositories”
“…trending repositories”
“…hot projects”
…
and others. List of queries is defined in actions.json. Here is final configuration for our agent:
###The code
Now let’s build service to handle requests from Google Assistant. We will build simple REST server, which handles POST requests (based on configuration above, both intent requests will be sent to https://githubactions.appspot.com/).
Project configuration
Our app requires a couple dependencies defined in app/build.gradle
file:
-
App Engine SDK
-
Google Actions Java SDK (my unofficial library)
-
Google HTTP Client Library for Java — to make calls to Github API. Not a good news for Android devs familiar with Okhttp and Retrofit — because of App Engine restrictions in threading, it’s really hard to make it working here.
-
Dagger 2 — Dependency injection framework to make our code a bit cleaner and easy to extend.
Final gradle files (able to build, run and deploy our GAE code) can be found here:
Servlet
Now let’s build code for processing requests from Google Assistant. At this level, it’s nothing more than just proper configuration of Google Actions Java SDK:
-
Build response handler. This object will be used to pass final responses to Google Assistant. Nothing really interesting, it just meets communication requirements (headers, format) Final code: AppEngineResponseHandler.
-
Build request handlers. Those are responsible for handling particular requests (our MAIN and TRENDING intents). Request handlers should process incoming request and generate tell/ask/permission response. In our app we’ll have only tell responses: greeting (MAIN) and randomly picked hot repository (TRENDING). In the future we’ll build more complex solutions on top of ask and permission responses. Final code for MainRequestHandler and TrendingRequestHandler (take a look at returned variable from getResponse() methods — in both cases we use
ResponseBuilder.tellResponse(…)
. -
Intents mapped to proper request handlers:
All dependencies for Assistant Actions can be found in AssistantModule class.
Final servlet code should be similar to this:
Line 15 is the place where all magic happens:
1) POST request comes from Google Assistant. It is parsed to RootRequest
object (lines: 18–20) and passed to assistantActions
.
2) Based on defined intents map, assistantAction
passes RootRequest
object to MainRequestHandler
or TrendingRequestHandler
.
3) Picked request handler generates tell response: RootResponse
.
4) Response is passed to AppEngineResponseHandler
which sends it back to Google Assistant.
Servlet Configuration
At the end you need to add App Engine servlet configuration to your project (files: web.xml and appengine-web.xml):
Their content should be self-explaining:
Now our app is ready to deploy. If the configuration is correct, all you have to do is:
$ ./gradlew app:appengineDeploy
Testing Assistant Actions
Even if you don’t have Google Home device, it’s still possible to simulate you newly created Assistant Actions. To do this you can use Google Home Web Simulator. All you need to do is:
1) $ gactions preview -action_package=app/action.json -invocation_name=Github
called from project’s root directory.
2) Sign-in and start: Web Simulator
More details can be found in official guide.
And that’s all! We’ve just built our very first preview version of Actions for Google Assistant. In future publications we’ll see how to extend its functionality.
Thanks for reading! 😊
Source code
Final source code of described project can be found on Github.
Author
Miroslaw Stanek
Head of Mobile Development @ Azimo Money Transfer
If you liked this post, you can share it with your followers or follow me on Twitter!