开发者控制台

步骤7: 添加BroadcastReceiver(VSK Fire TV)

步骤7: 添加BroadcastReceiver(VSK Fire TV)

在清单中添加BroadcastReceiver时,Fire TV将通过Alexa指令将您应用的任何意图发送到您指定的BroadcastReceiver类,例如AlexaDirectiveReceiver。在这个类中,您可以接受和处理Alexa发送到您应用的指令。

示例应用注意事项

示例应用报告已拥有BroadcastReceiver,因此您无需在此步骤中进行任何编码。在示例应用中,BroadCastReceiver名为AlexaDirectiveReceiver(在java/com/example/vskfiretv/company/receiver内)。

在清单中声明BroadcastReceiver和意图筛选条件

Fire TV上的VSK Agent将根据您的应用将收到的意图发送指令。在您应用的清单中,声明一个带有意图筛选条件的BroadcastReceiver,用于处理来自VSK Agent的Alexa指令和其他功能报告。此BroadcastReceiver将在其意图筛选条件中处理ACTION_ALEXA_DIRECTIVEACTION_REPORT_CAPABILITIES

在以下清单示例中,BroadcastReceiver的名称是AlexaDirectiveReceiver,这就是示例应用中命名BroadcastReceiver的方式。可以将此名称更改为您在应用中需要的任何BroadcastReceiver名称。

   <receiver
       android:name=".receiver.AlexaDirectiveReceiver"
       android:enabled="true"
       android:exported="true"
       android:permission="com.amazon.alexa.androidapplicationagent.permission.SEND_DATA">
       <!--接收Alexa指令的意图操作-->
       <intent-filter>
           <action android:name="com.amazon.alexa.vsk_app_agent_api.ACTION_ALEXA_DIRECTIVE" />
       </intent-filter>
       <!--VSK Agent向应用请求的意图操作,用于报告其动态功能-->
       <intent-filter>
           <action android:name="com.amazon.alexa.vsk_app_agent_api.ACTION_REPORT_CAPABILITIES" />
       </intent-filter>
   </receiver>
示例应用注意事项

有关如何声明BroadcastReceiver和意图筛选条件的示例,请参阅示例应用(在app/src内)中的AndroidManifest.xml

添加BroadcastReceiver Java类

添加一个BroadcastReceiver Java类(例如AlexaDirectiveReceiver),该类可以处理从VSK Agent发送的各种意图。您可以根据需要随意命名接收器,只要该类与您的清单声明(在上一部分中)相匹配。

BroadcastReceiver类负责处理Alexa收到的所有指令。Alexa向VSK Agent发送指令,然后VSK Agent将指令传达给您的BroadcastReceiver。

以下是BroadcastReceiver类的样板示例:

// -------------------------------\
// MyDirectiveReceiver.java
// -------------------------------/
public class MyDirectiveReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {

    if (VSKIntentConstants.ACTION_ALEXA_DIRECTIVE.equals(intent.getAction())) {
      String namespace = intent.getStringExtra(VSKIntentConstants.EXTRA_DIRECTIVE_NAMESPACE);
      String name = intent.getStringExtra(VSKIntentConstants.EXTRA_DIRECTIVE_NAME);
      String payload = intent.getStringExtra(VSKIntentConstants.EXTRA_DIRECTIVE_PAYLOAD);
      PendingIntent response = intent.getParcelableExtra(VSKIntentConstants.EXTRA_DIRECTIVE_RESPONSE_PENDING_INTENT);

      boolean didSucceed = false;
      boolean sendResponse = true;
      if (namespace.equals("RemoteVideoPlayer") {
        if (name.equals("SearchAndPlay") {
          sendResponse = false; //该操作的处理是异步的,传递PendingIntent,并在我们知道该状态时进行回调
          handlePlay(payload, response); //提取实体并构建意图以深层链接到播放器活动
        } else if (name.equals("SearchAndDisplayResults") {
          didSucceed = handleSearch(payload); //提取实体并构建意图以深层链接到搜索活动
        }
      } else if (name.equals("PlaybackController") {
        // ...
      } else if // ...
      if (response != null && sendResponse) {
        Intent success = new Intent().putExtra(VSKIntentConstants.EXTRA_DIRECTIVE_STATUS, didSucceed);
        try {
          response.send(context, 0, success);
        } catch(PendingIntent.CanceledException e) {
          //我们进行回复、记录错误可能花了太长时间
        }
      }
    }
  }
}

此代码接收来自Alexa的指令,并具有占位符,可以根据内容执行一些逻辑。如果成功处理了该指令,则您将发送一个状态为成功的响应。响应以truefalse布尔值作为成功参数。

下一步为步骤8: 对指令做出反应,详细介绍了您的应用将收到的各种指令以及处理它们的方式。

示例应用注意事项

与上面的样板示例相比,示例应用中的AlexaDirectiveReceiver类具有更详细的逻辑和其他环境。该示例应用尝试显示更多用于处理指令的实际环境信息。

测试您的动态功能集成(可选)

通过动态集成(无论您是使用VSK Agent Client Library还是原始VSKApplicationAgentAPI程序包进行集成),您可以调用sendCapabilityTestDirective方法来测试应用的集成。调用此方法会致使Fire OS路由代理回报用于将应用作为VSK指令调用的功能。

此方法不是为了测试任何特定的指令处理是否正常工作。其目的是验证设备通信通道是否正常运行,这样您就可以看到自己正确地报告了应用的功能,并且您的BroadcastReceiver可以从路由代理接收意图,而无需连接到Fire TV设备或创建请求/表述。

以下代码显示了如何调用sendCapabilityTestDirective()方法。

// -------------------------------\
// MyDirectiveReceiver.java
// -------------------------------/
public class MyDirectiveReceiver extends BroadcastReciever {

    @Override
    public void onReceive(Context context, Intent intent) {

        if (VSKIntentConstants.ACTION_ALEXA_DIRECTIVE.equals(intent.getAction())) {
            String namespace = intent.getStringExtra(VSKIntentConstants.EXTRA_DIRECTIVE_NAMESPACE);
            String name = intent.getStringExtra(VSKIntentConstants.EXTRA_DIRECTIVE_NAME);
            String payload = intent.getStringExtra(VSKIntentConstants.EXTRA_DIRECTIVE_PAYLOAD);

            if (VSKIntentConstants.TEST_DIRECTIVE_NAMESPACE.equals(namespace) &&
                VSKIntentConstants.TEST_DIRECTIVE_NAME.equals(name)) {
                log.d(TAG, payload);
            }
            ...
        }
        ...
     }
}

requestTestDirectiveFromVSKAgent()方法将触发VSK路由代理向您的应用发送测试指令的操作,无需向Alexa发出请求/表述。此意图的有效负载将是路由代理为您的应用记录在案的功能的JSON列表。例如:

{"capabilities":[{"configurations":{"operations":["SearchAndDisplayResults","SearchAndPlay"],"catalogs":[{"type":"VIDEO_PUBLIC_CATALOG_IDENTIFIER","sourceId":"imdb"}]},"interface":"Alexa.RemoteVideoPlayer","type":"AlexaInterface","version":"3.1"},{"interface":"Alexa.PlaybackController","type":"AlexaInterface","version":"3","supportedOperations":["Play","Pause","Stop"]}]}

示例应用注意事项

要查看示例应用中的sendCapabilityTestDirective() 方法, 请参看 DynamicCapabilityReporter 类(在 app/java/com/example/vskfiretv/company/reporter内), 特别是以下部分:

public void requestTestDirectiveFromVSKAgent() {
    Log.i(TAG, “请求VSK Agent将测试指令发送到应用”);
    client.sendCapabilityTestDirective();
    Log.i(TAG, "测试指令请求已完成");
}

示例应用在MainActivity.java中调用此方法。示例应用使用ExecutorService启动与主线程分开的后台线程:

//运行一个后台线程来报告功能
final ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(reporter::reportDynamicCapabilities);

后续步骤

转到下一步: 步骤8: 对指令做出反应