使用API.AI和Google智能助理,我正在请求获取用户名称和位置的权限 . 目的是我能够一次请求许可,随后对我的行动的请求将不需要再次询问(因为每次用户与我的行动谈话时,这将导致非常愚蠢的对话) .
我发现的是,我只是将意图中的信息与 actions_intent_PERMISSION
相关联 - 信息已经被授予了许可 . (在下面的示例代码中 - 它最终会重新请求所有其他意图的权限 . )
我也没有在我的Action的调用之间看到这种权限 . 因此,每次触发操作时,都会(再次)询问他们是否授予操作权限 .
这两种行为都很奇怪 . 通常,应用程序模型不要求我在应用程序的调用之间或者甚至在应用程序“运行”时重新授权对资源的许可 . 甚至网页也会在会话期间保留授权 . 我做错了什么,或者这是出于预期的行为?
正在执行的代码(这是在Google Cloud Functions中运行的,并且还有一些通过Promise进行这些调用的其他结构 - 这只是代码的相关部分) . res.send(200)
只是向API.AI表明它应该使用那里定义的响应,并且没有问题 . return Promise.resolve(null);
只是确保不执行其他回退/错误条件 .
exports.process = function( req, res ){
var app = new ApiAiApp({request:req, response:res});
if( app.isPermissionGranted() ){
res.send( 200 );
return Promise.resolve( null );
} else {
return askPermission( req, res, app );
}
};
var askPermission = function( req, res, app ){
//app.tell('foo');
let namePermission = app.SupportedPermissions.NAME;
let preciseLocationPermission = app.SupportedPermissions.DEVICE_PRECISE_LOCATION;
// Ask for more than one permission. User can authorize all or none.
app.askForPermissions('To address you by name and know your location',
[namePermission, preciseLocationPermission]);
return Promise.resolve( null );
};
处理 actions_intent_PERMISSION
请求的API.AI Intent:
另一个应具有用户/位置有效负载的Intent,但永远不会使用该信息调用
模拟器的屏幕截图显示它总是要求许可,除非特别授予它:
最初连接时发送的JSON:
{
"originalRequest": {
"source": "google",
"version": "2",
"data": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
}
]
},
"inputs": [
{
"rawInputs": [
{
"query": "talk to my test app",
"inputType": "KEYBOARD"
}
],
"intent": "actions.intent.MAIN"
}
],
"user": {
"locale": "en-US",
"userId": "APhe68HKWmHGe9cojGOMrX9WKQ0l"
},
"device": {},
"conversation": {
"conversationId": "1499807128489",
"type": "NEW"
}
}
},
"id": "7e301f85-4178-4be6-8b7c-408bad3ef62b",
"timestamp": "2017-07-11T21:05:28.504Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "GOOGLE_ASSISTANT_WELCOME",
"speech": "",
"action": "input.welcome",
"actionIncomplete": false,
"parameters": {},
"contexts": [
{
"name": "google_assistant_welcome",
"parameters": {},
"lifespan": 0
},
{
"name": "actions_capability_screen_output",
"parameters": {},
"lifespan": 0
},
{
"name": "actions_capability_audio_output",
"parameters": {},
"lifespan": 0
},
{
"name": "google_assistant_input_type_keyboard",
"parameters": {},
"lifespan": 0
}
],
"metadata": {
"intentId": "f31e371a-db9e-4e00-8002-546ec14d40a9",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"nluResponseTime": 2,
"intentName": "Default Welcome Intent"
},
"fulfillment": {
"speech": "I'm not sure, I'm a little confused.",
"messages": [
{
"type": 0,
"speech": "I'm not sure, I'm a little confused."
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "1499807128489"
}
JSON发送后请求许可,我已经批准了 . 正如预期的那样 originalRequest.data.user
有名称, originalRequest.data.device
现在有位置 .
{
"originalRequest": {
"source": "google",
"version": "2",
"data": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
}
]
},
"inputs": [
{
"rawInputs": [
{
"query": "yes",
"inputType": "KEYBOARD"
}
],
"arguments": [
{
"rawText": "yes",
"textValue": "true",
"name": "PERMISSION"
}
],
"intent": "actions.intent.PERMISSION"
}
],
"user": {
"profile": {
"displayName": "Allen Firstenberg",
"givenName": "Allen",
"familyName": "Firstenberg"
},
"locale": "en-US",
"userId": "APhe68HKWmHGe9cojGOMrX9WKQ0l"
},
"device": {
"location": {
"coordinates": {
"latitude": 37.4219806,
"longitude": -122.0841979
}
}
},
"conversation": {
"conversationId": "1499807128489",
"type": "ACTIVE",
"conversationToken": "[\"_actions_on_google_\"]"
}
}
},
"id": "7a75593e-55d0-4962-ad91-564d47e5df13",
"timestamp": "2017-07-11T21:05:43.391Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "actions_intent_PERMISSION",
"speech": "",
"action": "",
"actionIncomplete": false,
"parameters": {},
"contexts": [
{
"name": "actions_capability_screen_output",
"parameters": {},
"lifespan": 0
},
{
"name": "_actions_on_google_",
"parameters": {},
"lifespan": 99
},
{
"name": "actions_intent_permission",
"parameters": {
"PERMISSION": "true"
},
"lifespan": 0
},
{
"name": "actions_capability_audio_output",
"parameters": {},
"lifespan": 0
},
{
"name": "google_assistant_input_type_keyboard",
"parameters": {},
"lifespan": 0
}
],
"metadata": {
"intentId": "5d154d71-63f1-43a9-9c18-70d78bfd700f",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"nluResponseTime": 1,
"intentName": "Location result"
},
"fulfillment": {
"speech": "you're allowed",
"messages": [
{
"type": 0,
"speech": "you're allowed"
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "1499807128489"
}
在我获得许可(上面)后发送JSON,然后发出“简单测试”短语 . 请注意,用户和设备字段缺少授予权限的信息,但这是正确的意图 .
{
"originalRequest": {
"source": "google",
"version": "2",
"data": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
}
]
},
"inputs": [
{
"rawInputs": [
{
"query": "simple test",
"inputType": "KEYBOARD"
}
],
"arguments": [
{
"rawText": "simple test",
"textValue": "simple test",
"name": "text"
}
],
"intent": "actions.intent.TEXT"
}
],
"user": {
"locale": "en-US",
"userId": "APhe68HKWmHGe9cojGOMrX9WKQ0l"
},
"device": {},
"conversation": {
"conversationId": "1499807128489",
"type": "ACTIVE",
"conversationToken": "[\"_actions_on_google_\"]"
}
}
},
"id": "f1804e02-bafc-4656-8726-0955bfb4f75d",
"timestamp": "2017-07-11T21:05:55.001Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "simple test",
"speech": "",
"action": "",
"actionIncomplete": false,
"parameters": {},
"contexts": [
{
"name": "actions_capability_screen_output",
"parameters": {},
"lifespan": 0
},
{
"name": "_actions_on_google_",
"parameters": {},
"lifespan": 98
},
{
"name": "actions_capability_audio_output",
"parameters": {},
"lifespan": 0
},
{
"name": "google_assistant_input_type_keyboard",
"parameters": {},
"lifespan": 0
}
],
"metadata": {
"intentId": "48257e82-3615-4445-8ea2-be21980b7115",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"nluResponseTime": 4,
"intentName": "simple test"
},
"fulfillment": {
"speech": "",
"messages": [
{
"type": 0,
"speech": ""
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "1499807128489"
}
在两个会话之间执行此操作会产生相同类型的结果 .
1 回答
这是预期的行为 . 现在,我们建议您在用户ID的基础上保留用户许可的数据 . 要了解我们如何推荐这样做,请查看Name Psychic样本 . 在该示例中,我们使用Firebase Realtime DB在意图/对话中持久保存该用户的权限数据 .