Запрос-ответ

После получения запроса агентом самое время сформировать ответ и отправить его ассистенту.

Начнем с конца, с отправки. Предположим у вас уже есть содержимое ответа в переменной content. Есть 2 способа отправить это содержимое ассистенту.

Многословный:

Response response = request.createResponse();
response.setContent(content);
request.addResponse(response);

Однострочный:

request.addQuickResponse(content);

Однострочный ответ не позволит войти в Scope, выставить cookie, но если ответ окончательный и обжалованию не подлежит, одной строки достаточно.

Содержимое ответа

Для того, чтобы ассистент мог отобразить содержимое пользователю, оно должно быть сначала доставлено, а затем понято ассистентом. Несмотря на то, что методы Request.addQuickResponse() и Response.setContent() принимают Object, произвольный объект отправить не получится. Во-первых, не любой объект пройдет через Parcel (см. `Parcel.writeValue()). Во-вторых, не любой объект понятно как отобразить.

Ассистент поддерживает 3 основных типа содержимого и несколько вспомогательных.

Основные:

Вспомогательные:

CharSequence

Про CharSequence сказать можно немного. Поддерживаются стили (см. TextUtils.writeToParcel.

RemoteViews

Про RemoteViews тоже немного. Есть только одно важное отличие от appwidgets: списки не поддерживаются.

Bubble

Самый гибкий способ оформить ответ - это использовать класс Bubble. Он практически во всем повторяет RemoteViews, но содержит ряд удобных методов для обработки нажатий на кнопки.

Вот пример того, как можно обработать нажатие кнопки:

Bubble bubble = new Bubble(R.layout.bubble_mine);
bubble.makeOnClickRequest(R.id.btn1);

Если пользователь нажмет на кнопку с id равным R.id.btn1, то будет вызван метод onBubbleClick(Request) вашего агента, и Request.getDispatchId() будет равен R.id.btn1.

Важно понимать, что если обрабатывать нажатие таким образом, то будет сформирован новый запрос, на который агент должен сформировать новый ответ.

Чтобы обработать нажатие кнопки без формирования нового запроса, придется сделать что-то вроде этого:

PendingIntent template = PendingIntent.getActivity(MyAgent.this, 0, new Intent(), 0);
bubble.setPendingIntentTemplate(template);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://example.com")
bubble.setOnClickFillInIntent(R.id.btn1, intent);

Будет запущен браузер.

Также можно обрабатывать нажатия на весь баббл, используя методы makeOnBubbleClickRequest(), setOnBubbleClickRequest(PendingRequest.Builder) и setOnBubbleClickFillInIntent(Intent).

Utterance

Основной способ озвучить любое содержимое - это заключить его в Utterance. Один единственный конструктор Utterance(Object, CharSequence) принимает содержимое и его озвучку. Стоит ли говорить, что на содержимое Utterance накладываются те же ограничения, что и на содержимое непосредственно ответа.

Массивы и списки

Если в ответе содержится массив или список, то все его элементы будут отображены пользователю расположенными вертикально.