Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fetch device location using API AI?

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.

like image 365
Sai Avatar asked Dec 23 '16 01:12

Sai


2 Answers

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.

  1. To do so you need to click on the "Add follow-up intent" link on your intent. Note that the link will only appear when you hover it. Select the fallback option from the dropdown list and a child fallback intent will be created for you.

Screen shot for how to create a child fallback intent

  1. Click into the child fallback intent and enable "Use webhook".

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')
})
like image 164
Willow Yang Avatar answered Oct 20 '22 17:10

Willow Yang


There are three parts to this:

  1. Asking for permission
  2. Telling API.AI to handle the response
  3. Handling the information forwarded by API.AI

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:

enter image description here

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.

like image 2
Prisoner Avatar answered Oct 20 '22 16:10

Prisoner