Permissions and Google Home

Josh Feinberg
Dev Tutorials
Published in
4 min readMay 16, 2017

--

If you’ve read my past two posts you now know how to build a conversation action and hook it up to our own API. In the last lesson we hard coded the current bus stop location in the API, but wouldn’t it be so much better if we could find the closest stop to the device?

Well it turns out we can, we just need to ask permission!

Like Android, Google Home has a few user permissions that we can use. These include:

  1. NAME — lets you read the users name
  2. DEVICE_PRECISE_LOCATION — the current devices precise location, including the devices coordinates and readable address (includes DEVICE_COARSE_LOCATION permission)
  3. DEVICE_COARSE_LOCATION — the current devices location containing only the city and zip code

For our bus tracker we’ll need to request the devices precise location so we can get the latitude and longitude.

First though, lets setup our API.AI agent to handle this new permission request. To do that, we need to create one new intent, this time one called a Fallback Intent. A fallback intent is called when none of the other intents are matched. To create this, on the intents page next to the “Create Intent” button there is a menu option. Click this and one of the options will be to create a new fallback intent.

We’re also going to use Contexts for this. A context is used for passing information from previous intents. Lets add an Input Context called “request_permission”. We’ll also want to add an action of “find-bus” and a backup response in case our webhook doesn’t work. Finally, enable our webhook.

Our new fallback intent

Now that we have that setup we want to go back to our “Lookup Bus” intent and add “request_permission” as an Output Context.

That’s it for API.AI, now onto scripting our actually permission request.

In our scripts we’re going to change our actionsMap a little to look like this:

const actionMap = new Map();actionMap.set(‘bus-requested’, permissionChecker);actionMap.set(‘find-bus’, gotPermission);assistant.handleRequest(actionMap);

Now when we request a bus instead of grabbing the bus’ information immediately, we check for permission to use the devices location. Our fallback intent is called when we get notified if the user accepted our permission request or not.

Let’s take a look at those two functions starting with permissionChecker

function permissionChecker(assistant) {    const permission = assistant.SupportedPermissions.DEVICE_PRECISE_LOCATION;    assistant.askForPermission(‘To find the closest bus stop’, permission);}

First we define our permission using a helped constant and get the device’s precise location. The ApiAiAssistant class provides us a helper function askForPermission which takes two parameters. The first is a “context”, which is the explanation provided to the user for why you need this permission. It is used as a prefix to a string such as “[Context], I’ll just need to get your street address from Google, is that OK?”. The second is the permission that you would like to request.

After the user responds we use our ‘find-bus’ action and handle it in gotPermission

function gotPermission(assistant) {    if (assistant.isPermissionGranted()) {        findClosestBusStop(assistant)    } else {        assistant.tell(“I cannot find when the next bus is coming without your location.”);    }}

Our assistant object now contains if the permission requested was granted. If not, then our conversation ends here, otherwise let’s go find our closest bus stop.

Now remember our last action is about the permissions so what are we going to do about getting our bus number and direction!

Here is where we use the context ‘request_permission’ that we setup earlier.

var busNumber = assistant.getContext(“request_permission”).parameters[‘busnumber’];var busDirection = assistant.getContext(“request_permission”).parameters[‘direction’];

We can just get that context and now we have all our old parameters that were passed in with our welcome intent. To find the closest bus stop, the CTA API provides an endpoint to get all bus stop’s latitude and longitudes. All we have to do is use the haversine formula (explained here) to get our closest bus stop in meters. From there, our script is basically the same but no longer do we have a hard coded bus stop. We can also tell the user the cross streets of where this bus is going to be. Seems much more useful!

Here is what this sounds like when we test it on a device (Note: I did edit the sound a little so you all won’t know exactly where I live).

I’ll also provide the gist. Once again, all you need to do here is replace your API key. And once again, I am not a javascript developer so I apologize that I’m still getting used to some syntax and style things.

Now once you are all done, you can go ahead and submit it for approval. Google provides great instructions here on how to do it.

As an aside: The Actions on Google support team is absolutely incredible. Not only do they provide clear reasons for rejection but also ways that your action can be improved. They are quick on responses and I just wanted to give them a quick shout out.

Thanks for following along. I hope to continue working on Google Home actions so feel free to subscribe if you are curious to check out any other features I end up adding.

Click❤ below to recommend this to other Medium readers interested in AI, chatbots and development.

--

--