I am using GUI tools provided by API AI to create Actions. Is it possible to fetch device location? I have heard that this is possible by requesting permissions. Is this documented anywhere? An example/code snippet will be very useful.
The documentation is a bit unclear. I hope this can help someone.
All you have to do is create a child fallback intent for the intent you are requesting permissions from.
Screen shot for how to create a child fallback intent
Screen shot for how to configure the child fallback intent
That's it. Now once the permission is requested, the user response will be post back to you with the action which is configured in your child fallback intent.
See below for the webhook sample code.
'use strict';
const express = require('express')();
const router = require('express').Router();
const bodyParser = require('body-parser');
const ActionsSdkApp = require('actions-on-google').ActionsSdkApp;
const ApiAiApp = require('actions-on-google').ApiAiApp;
express.use(bodyParser.json({type: 'application/json'}));
// In aip.ai console, under Fulfillment set webhook url to
// https://[YOUR DOMAIN]/example/location
// don't forget to select "Enable webhook for all domains" for the DOMAIN field
router.post('/location', (req, res) => {
const app = new ApiAiApp({request: req, response: res});
const intent = app.getIntent();
switch(intent){
case 'input.welcome':
// you are able to request for multiple permissions at once
const permissions = [
app.SupportedPermissions.NAME,
app.SupportedPermissions.DEVICE_PRECISE_LOCATION
];
app.askForPermissions('Your own reason', permissions);
break;
case 'DefaultWelcomeIntent.DefaultWelcomeIntent-fallback':
if (app.isPermissionGranted()) {
// permissions granted.
let displayName = app.getUserName().displayName;
//NOTE: app.getDeviceLocation().address always return undefined for me. not sure if it is a bug.
// app.getDeviceLocation().coordinates seems to return a correct values
// so i have to use node-geocoder to get the address out of the coordinates
let coordinates = app.getDeviceLocation().address;
app.tell('Hi ' + app.getUserName().givenName + '! Your address is ' + address);
}else{
// permissions are not granted. ask them one by one manually
app.ask('Alright. Can you tell me you address please?');
}
break;
}
});
express.use('/example', router);
express.listen('8081', function () {
console.log('Example app is running')
})
There are three parts to this:
Asking for permission
A lot of people aren't mentioning the JSON body that needs to be made to request permissions in the first place. This is (poorly) documented at actions > assistant > helpers > User information since it doesn't really cover what needs to be sent if you're using API.AI.
In short, your JSON needs to look something like this:
{
"speech": "PLACEHOLDER_FOR_PERMISSION",
"data": {
"google": {
"expectUserResponse": true,
"isSsml": false,
"noInputPrompts": [],
"systemIntent": {
"intent": "actions.intent.PERMISSION",
"data": {
"@type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
"optContext": "To pick you up",
"permissions": [
"NAME",
"DEVICE_PRECISE_LOCATION"
]
}
}
}
}
}
Telling API.AI to handle the response
API.AI needs to know which Intent handles permission information. You do this by setting the Event to actions_intent_PERMISSION
.
This will look something like this:
You can set the Action to whatever makes sense for your webhook, and be sure to enable webhook fulfillment for the Intent as well.
If you need to keep track of where the permission request was initiated from, and handle it through a different Action, you can set a Context and have different handling Intents based on different Context settings.
The Fallback Intent method works because there is no better match at that point since you hadn't specified a regular Intent with actions_intent_PERMISSION
. It isn't the best choice, however, since it could match other situations from your user.
Get the info in your webhook
Your webhook will get a JSON object in the body.
The user's name and related information will be at the object path originalRequest.data.user.profile
.
Their location is provided at originalRequest.data.device.location
.
See Overview > Actions on Google lets you extend the functionality for references.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With