Google 어시스턴트와 Android 위젯 통합

1. 개요

첫 번째 앱 작업 Codelab에서는 건강/피트니스 BII 카테고리의 내장 인텐트(BII)를 구현하여 Google 어시스턴트를 샘플 피트니스 앱으로 확장하는 방법을 알아보았습니다.

앱 작업을 통해 사용자는 "Hey Google, ExampleApp에서 달리기 시작해 줘"와 같이 말하여 어시스턴트를 통해 특정 앱 기능을 바로 실행할 수 있습니다. 어시스턴트는 앱 실행 외에도 사용자에게 대화형 Android 위젯을 표시하여 대상 BII 요청을 처리합니다.

앱의 GET_EXERCISE_OBSERVATION BII 기능을 트리거하는 사용자 쿼리에 대한 응답으로\n위젯을 반환하는 어시스턴트를 보여주는 화면

빌드할 항목

이 Codelab에서는 Android 위젯을 반환하여 어시스턴트 사용자 요청을 처리하는 방법을 알아봅니다. 또한 다음의 내용을 알아봅니다.

  • 위젯을 맞춤설정하는 사용자 BII 매개변수
  • 위젯을 위한 어시스턴트의 텍스트 음성 변환(TTS) 소개
  • 내장 인텐트 참조에서 위젯 처리를 지원하는 BII 확인

사전 준비 사항

계속하기 전에 개발 환경이 앱 작업을 개발할 준비를 했는지 확인하세요. 다음 항목이 있어야 합니다.

  • git이 설치된 셸 명령어를 실행하는 터미널
  • Android 스튜디오 최신 공개 버전
  • 인터넷이 연결된 실제 또는 가상 Android 기기
  • Android 스튜디오, Google 앱, Google 어시스턴트 앱에 로그인된 Google 계정

실제 기기를 사용하는 경우 기기를 로컬 개발 머신에 연결하세요.

2. 작동 원리 이해

Google 어시스턴트는 자연어 이해(NLU)를 기반으로 사용자 요청을 읽고 어시스턴트 내장 인텐트(BII)에 매치합니다. 그런 다음 어시스턴트는 인텐트를 기능(BII를 구현함)에 매핑하며 개발자는 앱에서 이 인텐트에 기능을 등록합니다. 마지막으로 어시스턴트는 기능에 있는 세부정보를 기반으로 앱이 생성한 Android 위젯을 표시하여 사용자의 요청을 처리합니다.

이 Codelab에서는 GET_EXERCISE_OBSERVATION BII 지원을 등록하는 기능을 정의합니다. 이 기능을 통해 개발자는 어시스턴트에 FitActions 위젯 클래스에 대한 Android 인텐트를 생성하여 BII 요청을 처리하도록 지시합니다. 또한 위젯 클래스를 업데이트하여 어시스턴트가 사용자에게 표시할 맞춤설정된 위젯과 어시스턴트가 음성으로 안내할 TTS 소개를 생성합니다.

다음 다이어그램은 이 흐름을 보여줍니다.

어시스턴트 위젯 처리를 보여주는 흐름 다이어그램

FitActions 위젯

FitActions 샘플 앱에는 사용자가 홈 화면에 추가할 수 있는 운동 정보 위젯이 포함되어 있습니다. 이 위젯은 GET_EXERCISE_OBSERVATION BII를 트리거하는 사용자 쿼리를 처리하기에 적합합니다.

위젯 작동 방식

사용자가 홈 화면에 위젯을 추가하면 위젯은 기기 broadcast receiver를 핑합니다. 이 서비스는 앱의 AndroidManifest.xml 리소스에 있는 위젯의 리시버 정의에서 위젯에 관한 정보를 가져옵니다. 이 정보는 위젯을 나타내는 RemoteViews 객체를 생성하는 데 사용됩니다.

샘플 앱은 StatsWidgetProvider 클래스에 상응하는 리시버 widgets.StatsWidgetProvider를 정의합니다.

<!-- app/src/main/AndroidManifest.xml -->

<receiver
  android:name=".widgets.StatsWidgetProvider"
  android:exported="false">
  <intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
  </intent-filter>
  <meta-data
    android:name="android.appwidget.provider"
    android:resource="@xml/stats_widget" />
</receiver>

StatsWidgetProvider 클래스인 StatsWidgetProvider.ktStatsWidget 객체 생성 흐름을 관리하며 다음과 같은 작업을 처리합니다.

  • 위젯 인스턴스를 만들어 앱 데이터베이스의 운동 데이터로 채우기
  • 쉽게 읽을 수 있도록 formatDataAndSetWidget()으로 운동 데이터의 형식 지정
  • 운동 데이터를 사용할 수 없는 경우 setNoActivityDataWidget()을 사용하여 기본값 제공

어시스턴트 지원 추가

이 Codelab에서는 앱 작업 기능을 처리하도록 샘플 앱을 업데이트합니다. 변경사항은 다음과 같습니다.

  1. StatsWidget 객체의 인스턴스를 반환하도록 GET_EXERCISE_OBSERVATION BII 기능을 구성합니다.
  2. 다음과 같은 앱 작업 기능을 사용하도록 StatsWidget 클래스를 업데이트합니다.
    • 사용자가 "Hey Google, ExampleApp에서 달리기 통계 보여 줘"와 같이 말하여 특정 운동 통계를 확인할 수 있도록 BII 매개변수 사용
    • TTS 소개 문자열 제공
    • 특별한 사례 관리(예: 사용자 쿼리에 운동 유형 매개변수가 포함되지 않는 경우)

3. 개발 환경 준비

기본 파일 다운로드

다음 명령어를 실행하여 샘플 앱의 GitHub 저장소를 클론합니다.

git clone --branch start-widget-codelab https://github.com/actions-on-google/appactions-fitness-kotlin.git

저장소를 클론한 후에는 다음 단계에 따라 Android 스튜디오에서 엽니다.

  1. Welcome to Android Studio 대화상자에서 Import project를 클릭합니다.
  2. 저장소를 클론한 폴더를 찾아 선택합니다.

Codelab 완료 후의 앱 버전을 보려면 --branch master 플래그를 사용하여 샘플 앱 저장소를 클론하세요.

Android 애플리케이션 ID 변경

이 Codelab 뒷부분에서는 Google 어시스턴트 플러그인을 사용하여 실제 기기나 가상 기기에서 작업을 테스트합니다. 테스트 도구를 실행하려면 먼저 앱을 Google Play Console의 프로젝트에 업로드해야 합니다. Play Console에 앱을 업로드할 때 '중복된 패키지 이름' 오류가 발생하지 않도록 샘플 앱의 applicationId를 고유하게 변경합니다(Google Play에서는 applicationId가 같은 두 앱을 업로드할 수 없음).

  1. app/build.gradle에서 applicationId 값인 PUT_YOUR_APPLICATION_ID_HERE를 고유 ID(예: com.codelabs.myname)로 업데이트합니다. Android 애플리케이션 ID에 관한 자세한 내용은 애플리케이션 ID 설정을 참고하세요.
  2. app/src/res/xml/shortcuts.xml을 열고 android:targetPackage의 인스턴스 2개를 고유한 applicationId로 업데이트합니다.

Play Console에 업로드

Android 스튜디오에서 Google 어시스턴트 플러그인을 사용하려면 먼저 Google Play Console에서 프로젝트에 앱을 업로드해야 합니다. Android 스튜디오에서 앱을 빌드하고 내부 초안 버전으로 Play Console에 업로드합니다.

Android 스튜디오에서 앱을 빌드하는 방법은 다음과 같습니다.

  1. Build > Generate Signed Bundle / APK로 이동합니다.
  2. Android App Bundle을 선택하고 Next를 클릭합니다.
  3. 앱 서명에서 세부정보를 입력하고 Next를 클릭합니다. Destination Folder 섹션에서 번들이 생성되는 경로를 추적합니다.
  4. prodRelease 또는 release 빌드 변형을 선택하고 Finish를 클릭합니다.

Play Console에서 방금 만든 App Bundle을 새로운 앱으로 업로드합니다.

  1. 모든 앱 페이지에서 앱 만들기를 클릭합니다.
  2. 앱 이름 상자에 앱 이름(예: '위젯 Codelab')을 입력합니다.
  3. 앱 또는 게임에서 을 선택합니다.
  4. 무료 또는 유료에서 무료를 선택합니다.
  5. 표시된 선언에 동의합니다.
  6. 앱 만들기를 클릭합니다.
  7. Play Console 사이드 메뉴에서 테스트로 이동하여 내부 테스트 페이지를 찾습니다.
  8. 이 페이지에서 새 버전 만들기를 클릭합니다.
  9. 메시지가 표시되면 계속을 클릭하여 Google Play 앱 서명에 동의합니다.
  10. App Bundle 및 APK 패널에서 이전 단계에서 생성한 AAB 파일을 업로드합니다. 이 파일은 프로젝트의 app/prod/release 또는 app/release 디렉터리에 있을 가능성이 큽니다. 저장을 클릭합니다.

테스트 플러그인 설치

Google 어시스턴트 플러그인을 사용하면 테스트 기기에서 앱 작업을 테스트할 수 있습니다. Google 어시스턴트 플러그인은 Android 기기의 Google 앱을 통해 어시스턴트에 정보를 전송하는 방식으로 작동합니다. 아직 플러그인이 없는 경우 다음 단계를 따라 설치하세요.

  1. File > Settings(MacOS의 경우 Android Studio > Preferences)로 이동합니다.
  2. Plugins 섹션에서 Marketplace로 이동하여 'Google Assistant'를 검색합니다. 수동으로 테스트 도구를 다운로드하여 설치할 수도 있습니다.
  3. 도구를 설치하고 Android 스튜디오를 다시 시작합니다.

기기에서 앱 테스트

앱을 추가로 변경하기 전에 샘플 앱의 기능을 파악하면 도움이 될 수 있습니다.

다음과 같이 테스트 기기에서 앱을 실행합니다.

  1. Android 스튜디오에서 실제 기기나 가상 기기를 선택하고 Run > Run app을 선택하거나 툴바에서 RunAndroid 스튜디오의 Run app 아이콘을 클릭합니다.
  2. 홈 버튼을 길게 눌러 어시스턴트를 설정하고 작동을 확인합니다. 아직 로그인하지 않았다면 기기에서 어시스턴트에 로그인해야 합니다.

Android 가상 기기에 관한 자세한 내용은 가상 기기 만들기 및 관리를 참고하세요.

앱을 간단히 탐색하여 앱의 기능을 확인합니다. 앱은 10가지 운동 활동을 자동 입력하고 활동 정보를 첫 번째 뷰에 표시합니다.

기존 위젯 사용해 보기

  1. 버튼을 탭하여 테스트 기기의 홈 화면으로 이동합니다.
  2. 홈 화면의 빈 공간을 길게 누르고 위젯을 선택합니다.
  3. 위젯 목록을 아래로 스크롤하여 FitActions로 이동합니다.
  4. FitActions 아이콘을 길게 누르고 홈 화면에 위젯을 배치합니다.

기기 홈 화면에 있는 FitActions 위젯을 보여주는 스크린샷

4. 앱 작업 추가

이 단계에서는 GET_EXERCISE_OBSERVATION BII 기능을 추가합니다. shortcuts.xml에 새 capability 요소를 추가하면 됩니다. 이 기능은 기능이 트리거되는 방식과 BII 매개변수가 사용되는 방식, 요청을 처리하기 위해 호출할 Android 인텐트를 지정합니다.

  1. 이 구성을 사용하여 샘플 프로젝트 shortcuts.xml 리소스에 새 capability 요소를 추가합니다.
    <!-- fitnessactions/app/src/main/res/xml/shortcuts.xml -->
    
    <capability android:name="actions.intent.GET_EXERCISE_OBSERVATION">
      <app-widget
        android:identifier="GET_EXERCISE_OBSERVATION"
        android:targetClass="com.devrel.android.fitactions.widgets.StatsWidgetProvider"
        android:targetPackage="PUT_YOUR_APPLICATION_ID_HERE">
        <parameter
          android:name="exerciseObservation.aboutExercise.name"
          android:key="aboutExerciseName"
          android:required="true">
        </parameter>
        <extra android:name="hasTts" android:value="true"/>
      </app-widget>
      <!-- Add Fallback Intent-->
    </capability>
    
    android:targetPackage 값인 PUT_YOUR_APPLICATION_ID_HERE를 고유한 applicationId로 바꿉니다.

이 기능은 GET_EXERCISE_OBSERVATION BII를 app-widget 인텐트에 매핑하므로 BII가 트리거될 때 위젯이 인스턴스화되어 사용자에게 표시됩니다.

어시스턴트는 위젯을 트리거하기 전에 사용자 쿼리에서 지원되는 BII 매개변수를 추출합니다. 이 Codelab에는 사용자가 요청한 운동 유형을 나타내는 BII 매개변수 exerciseObservation.aboutExercise.name이 필요합니다. 앱에서 '달리기', '걷기', '자전거 타기'라는 세 가지 운동 유형을 지원하므로 인라인 인벤토리를 제공하여 어시스턴트에 이러한 지원 값을 알립니다.

  1. GET_EXERCISE_OBSERVATION 기능 위에 있는 이 구성을 shortcuts.xml에 추가하여 인벤토리 요소를 정의합니다.
    <!-- shortcuts.xml -->
    
    <!-- shortcuts are bound to the GET_EXERCISE_OBSERVATION capability and
         represent the types of exercises supported by the app. -->
    
    <shortcut
      android:shortcutId="running"
      android:shortcutShortLabel="@string/activity_running">
      <capability-binding android:key="actions.intent.GET_EXERCISE_OBSERVATION">
        <parameter-binding
          android:key="exerciseObservation.aboutExercise.name"
          android:value="@array/runningSynonyms"/>
      </capability-binding>
    </shortcut>
    
    <shortcut
      android:shortcutId="walking"
      android:shortcutShortLabel="@string/activity_walking">
      <capability-binding android:key="actions.intent.GET_EXERCISE_OBSERVATION">
        <parameter-binding
          android:key="exerciseObservation.aboutExercise.name"
          android:value="@array/walkingSynonyms"/>
      </capability-binding>
    </shortcut>
    
    <shortcut
      android:shortcutId="cycling"
      android:shortcutShortLabel="@string/activity_cycling">
      <capability-binding android:key="actions.intent.GET_EXERCISE_OBSERVATION">
        <parameter-binding
          android:key="exerciseObservation.aboutExercise.name"
          android:value="@array/cyclingSynonyms"/>
      </capability-binding>
    </shortcut>
    
    <capability android:name="actions.intent.GET_EXERCISE_OBSERVATION">
      <!-- ... -->
    </capability>
    

대체 인텐트 추가

대체 인텐트는 기능에 필요한 매개변수가 쿼리에 없어 사용자 쿼리를 처리할 수 없는 상황을 해결합니다. GET_EXERCISE_OBSERVATION 기능에는 android:required="true" 속성으로 지정된 exerciseObservation.aboutExercise.name 매개변수가 필요합니다. 이러한 상황에서 어시스턴트는 쿼리에 제공된 매개변수가 없더라도 요청을 성공적으로 처리하기 위해 개발자에게 대체 인텐트 정의를 요구합니다.

  1. shortcuts.xml에서 다음 구성을 사용하여 GET_EXERCISE_OBSERVATION 기능에 대체 인텐트를 추가합니다.
    <!-- shortcuts.xml -->
    
    <capability android:name="actions.intent.GET_EXERCISE_OBSERVATION">
    
      <app-widget>
        <!-- ... -->
      </app-widget>
    
      <!-- Fallback intent with no parameters needed to successfully execute.-->
      <intent
        android:identifier="GET_EXERCISE_OBSERVATION_FALLBACK"
        android:action="android.intent.action.VIEW"
        android:targetClass="com.devrel.android.fitactions.widgets.StatsWidgetProvider">
      </intent>
    </capability>
    

샘플 구성에서 대체 처리는 Extra 데이터에 매개변수가 없는 Android 인텐트입니다.

5. 어시스턴트용 위젯 사용 설정

GET_EXERCISE_OBSERVATION 기능을 설정한 상태에서 앱 작업 음성 호출을 지원하도록 위젯 클래스를 업데이트합니다.

위젯 확장 프로그램 라이브러리 추가

앱 작업 위젯 확장 프로그램 라이브러리를 활용하면 음성 전달 어시스턴트 경험을 위한 위젯 개선이 가능합니다. 특히 위젯에 맞춤 TTS 소개를 제공할 수 있습니다.

  1. 샘플 앱 /app/build.gradle 리소스에 위젯 확장 프로그램 라이브러리 종속 항목을 추가합니다.
    // app/build.gradle
    
    dependencies {
      //...
      implementation "com.google.assistant.appactions:widgets:0.0.1"
    }
    
    Android 스튜디오에 표시되는 경고 상자에서 Sync Now를 클릭합니다. build.gradle을 변경할 때마다 동기화하면 앱을 빌드할 때 발생하는 오류를 방지할 수 있습니다.

위젯 서비스 추가

서비스는 백그라운드에서 장기 실행 작업을 실행할 수 있는 애플리케이션 구성요소입니다. 앱은 위젯 요청을 처리할 서비스를 제공해야 합니다.

  1. 다음 구성으로 샘플 앱의 AndroidManifest.xml 리소스에 서비스를 추가합니다.
    <!-- AndroidManifest.xml -->
    <service
       android:name=".widgets.StatsWidgetProvider"
       android:enabled="true"
       android:exported="true">
       <intent-filter>
           <action
               android:name="com.google.assistant.appactions.widgets.PIN_APP_WIDGET" />
       </intent-filter>
    </service>
    
    

위젯 처리를 트리거하는 음성 쿼리 중에 어시스턴트는 이 서비스를 사용하여 앱에 요청을 보냅니다. 서비스는 이 요청을 BII 데이터와 함께 수신합니다. 서비스는 이 데이터를 사용하여 어시스턴트 내에서 렌더링할 RemoteView 위젯 객체를 생성합니다.

위젯 클래스 업데이트

이제 앱이 GET_EXERCISE_OBSERVATION 기능 요청을 위젯 클래스로 라우팅하도록 구성되었습니다. 다음으로 BII 매개변수 값을 사용하여 사용자 요청에 맞춤설정된 위젯 인스턴스를 생성하도록 StatsWidget.kt 클래스를 업데이트하겠습니다.

  1. StatsWidget.kt 클래스를 열고 앱 작업 위젯 확장 프로그램 라이브러리를 가져옵니다.
    // StatsWidget.kt
    
    // ... Other import statements
    import com.google.assistant.appactions.widgets.AppActionsWidgetExtension
    
    
  2. 위젯에 채워야 하는 정보를 결정할 때 사용하는 다음 비공개 변수를 추가합니다.
    // StatsWidget.kt
    
    private val hasBii: Boolean
    private val isFallbackIntent: Boolean
    private val aboutExerciseName: String
    private val exerciseType: FitActivity.Type
    
  3. 클래스가 어시스턴트에서 전달된 위젯 옵션 데이터를 사용하도록 init 함수를 추가합니다.
    // StatsWidget.kt
    
    init {
      val optionsBundle = appWidgetManager.getAppWidgetOptions(appWidgetId)
      val bii = optionsBundle.getString(AppActionsWidgetExtension.EXTRA_APP_ACTIONS_BII)
      hasBii = !bii.isNullOrBlank()
      val params = optionsBundle.getBundle(AppActionsWidgetExtension.EXTRA_APP_ACTIONS_PARAMS)
    
      if (params != null) {
        isFallbackIntent = params.isEmpty
        if (isFallbackIntent) {
          aboutExerciseName = context.resources.getString(R.string.activity_unknown)
        } else {
            aboutExerciseName = params.get("aboutExerciseName") as String
          }
      } else {
          isFallbackIntent = false
          aboutExerciseName = context.resources.getString(R.string.activity_unknown)
      }
      exerciseType = FitActivity.Type.find(aboutExerciseName)
    }
    
    

이러한 업데이트를 통해 StatsWidget.kt 클래스가 GET_EXERCISE_OBSERVATION 기능으로 생성된 Android 인텐트에 응답하는 방법을 살펴보겠습니다.

  • optionsBundle = 번들
    • 번들은 프로세스 경계를 교차하여 활용하거나 인텐트가 있는 활동 간에 사용하는 객체입니다. 구성 변경 시 일시적인 상태를 저장하는 데에도 사용됩니다. 어시스턴트는 Bundle 객체를 사용하여 위젯에 구성 데이터를 전달합니다.
  • bii = actions.intent.GET_EXERCISE_OBSERVATION
    • BII 이름은 번들에서 AppActionsWidgetExtension을 사용하여 확인할 수 있습니다.
  • hasBii = true
    • BII가 있는지 확인합니다.
  • params = Bundle[{aboutExerciseName=running}]
    • 앱 작업으로 생성된 특수 번들은 위젯 옵션 Bundle 내에 중첩되며 BII의 키-값 쌍을 포함합니다. 여기에서 running은 예시 쿼리 "Hey Google, ExampleApp에서 달리기 통계 보여 줘"에서 추출된 값입니다.
  • isFallbackIntent = false
    • Extras 인텐트에 필수 BII 매개변수가 있는지 확인합니다.
  • aboutExerciseName = running
    • aboutExerciseName의 인텐트 Extras 값을 가져옵니다.
  • exerciseType = RUNNING
    • aboutExerciseName을 사용하여 상응하는 데이터베이스 유형 객체를 찾습니다.

이제 StatsWidget 클래스가 수신되는 앱 작업 Android 인텐트 데이터를 처리할 수 있으므로 위젯 생성 흐름 로직을 업데이트하여 위젯이 앱 작업으로 트리거되었는지 확인하겠습니다.

  1. StatsWidget.kt에서 updateAppWidget() 함수를 다음 코드로 바꿉니다.
    // StatsWidget.kt
    
    fun updateAppWidget() {
       /**
        * Checks for App Actions BII invocation and if BII parameter data is present.
        * If parameter data is missing, use data from last exercise recorded to the
        *  fitness tracking database.
        */
       if (hasBii && !isFallbackIntent) {
           observeAndUpdateRequestedExercise()
       } else observeAndUpdateLastExercise()
    }
    
    

위 코드는 새 함수 observeAndUpdateRequestedExercise를 참조합니다. 이 함수는 앱 작업 Android 인텐트에서 전달한 exerciseType 매개변수 데이터를 사용하여 위젯 데이터를 생성합니다.

  1. 다음 코드를 사용하여 observeAndUpdateRequestedExercise 함수를 추가합니다.
    // StatsWidget.kt
    
    /**
    * Create and observe the last exerciseType activity LiveData.
    */
    private fun observeAndUpdateRequestedExercise() {
      val activityData = repository.getLastActivities(1, exerciseType)
    
       activityData.observeOnce { activitiesStat ->
           if (activitiesStat.isNotEmpty()) {
               formatDataAndSetWidget(activitiesStat[0])
               updateWidget()
           } else {
               setNoActivityDataWidget()
               updateWidget()
           }
       }
    }
    
    

위 코드에서는 앱에 있는 기존 저장소 클래스를 사용하여 앱의 로컬 데이터베이스에서 피트니스 데이터를 가져옵니다. 이 클래스는 데이터베이스 액세스를 단순화하는 API를 제공합니다. 저장소는 데이터베이스에 쿼리를 실행할 때 LiveData 객체를 노출하는 방식으로 작동합니다. 개발자는 코드에서 최신 피트니스 활동을 가져오는 LiveData를 관찰합니다.

TTS 사용 설정

위젯을 표시할 때 어시스턴트가 음성으로 안내할 TTS 문자열을 제공할 수 있습니다. 위젯에 청취 가능한 컨텍스트를 제공하려면 TTS 문자열을 포함하는 것이 좋습니다. 이 기능은 앱 작업 위젯 확장 프로그램 라이브러리에서 제공하며, 이를 통해 어시스턴트의 위젯과 함께 제공되는 텍스트 및 TTS 소개를 설정할 수 있습니다.

TTS 소개를 제공하기에 좋은 위치는 앱 데이터베이스에서 반환된 활동 데이터의 형식을 지정하는 formatDataAndSetWidget 함수입니다.

  1. StatsWidget.kt에서 다음 코드를 formatDataAndSetWidget 함수에 추가합니다.
    // StatsWidget.kt
    
    private fun formatDataAndSetWidget(
      activityStat: FitActivity,
    ) {
          // ...
    
          // Add conditional for hasBii for widget with data
          if (hasBii) {
             // Formats TTS speech and display text for Assistant
             val speechText = context.getString(
                 R.string.widget_activity_speech,
                 activityExerciseTypeFormatted,
                 formattedDate,
                 durationInMin,
                 distanceInKm
             )
             val displayText = context.getString(
                 R.string.widget_activity_text,
                 activityExerciseTypeFormatted,
                 formattedDate
             )
             setTts(speechText, displayText)
          }
    }
    
    

위 코드는 두 가지 문자열 리소스를 참조합니다. 하나는 음성 안내용, 하나는 텍스트 표시용입니다. TTS 권장사항을 보려면 위젯 동영상의 텍스트 음성 변환 스타일 권장사항 부분을 확인하세요. 또한 이 샘플은 위젯 인스턴스에 TTS 정보를 제공하는 새로운 함수인 setTts를 참조합니다.

  1. 다음 코드를 사용하여 새 setTts 함수를 StatsWidget.kt에 추가합니다.
    // StatsWidget.kt
    
    /**
     * Sets TTS to widget
     */
    private fun setTts(
      speechText: String,
      displayText: String,
    ) {
      val appActionsWidgetExtension: AppActionsWidgetExtension =
          AppActionsWidgetExtension.newBuilder(appWidgetManager)
            .setResponseSpeech(speechText)  // TTS to be played back to the user
            .setResponseText(displayText)  // Response text to be displayed in Assistant
            .build()
    
      // Update widget with TTS
      appActionsWidgetExtension.updateWidget(appWidgetId)
    }
    

마지막으로 운동 데이터베이스가 요청된 운동 유형에 빈 데이터를 반환하는 경우의 TTS 정보를 설정하여 TTS 로직을 완성합니다.

  1. 다음 코드로 StatsWidget.ktsetNoActivityDataWidget() 함수를 업데이트합니다.
    // StatsWidget.kt
    
    private fun setNoActivityDataWidget() {
      // ...
      // Add conditional for hasBii for widget without data
      if (hasBii) {
        // formats speech and display text for Assistant
        // https://developers.google.com/assistant/app/widgets#library
        val speechText =
          context.getString(R.string.widget_no_activity_speech, aboutExerciseName)
        val displayText =
          context.getString(R.string.widget_no_activity_text)
    
        setTts(speechText, displayText)
      }
    }
    

6. 앱 작업 테스트

Google 어시스턴트 플러그인을 사용하면 개발 중에 테스트 기기에서 어시스턴트 앱 작업을 미리 볼 수 있습니다. 이 도구로 앱 작업의 인텐트 매개변수를 조정하여 사용자가 어시스턴트에 요청할 때 사용할 만한 다양한 방식을 작업에서 어떻게 처리하는지 테스트해 보세요.

미리보기 만들기

플러그인으로 앱 작업을 테스트하는 방법은 다음과 같습니다.

  1. Tools > Google Assistant > App Actions Test Tool로 이동합니다. Android 스튜디오에 로그인하라는 메시지가 표시될 수 있습니다. 이 경우에는 앞서 Google Play Console에서 사용한 것과 동일한 계정을 사용하세요.
  2. Create Preview를 클릭하여 미리보기를 만듭니다.

예상 운동 유형 테스트

테스트 도구에서 다음 단계에 따라 앱에서 마지막으로 완료된 달리기 정보를 보여주는 위젯을 반환합니다.

  1. 먼저, 도구에서 BII를 선택하고 구성하라는 단계가 안내되면 actions.intent.GET_EXERCISE_OBSERVATION을 선택합니다.
  2. exerciseObservation 상자에서 기본 운동 이름을 climbing에서 run으로 업데이트합니다.
  3. Run App Action을 클릭합니다.

Google 어시스턴트 플러그인을 사용하여 반환된 위젯을 보여주는 화면

예상치 못한 운동 유형 테스트

테스트 도구에서 예상치 못한 운동 유형을 테스트하는 방법은 다음과 같습니다.

  1. exerciseObservation 상자에서 name 값을 Run에서 Climbing으로 업데이트합니다.
  2. Run App Action을 클릭합니다.

어시스턴트는 'No activity found' 정보를 표시하는 위젯을 반환합니다.

Google 어시스턴트 플러그인을 사용하여 반환된 운동 정보가 없는 위젯을 보여주는 화면

대체 인텐트 테스트

대체 인텐트를 트리거하는 쿼리는 모든 운동 유형에서 마지막으로 기록된 활동에 관한 정보를 표시하는 위젯을 반환해야 합니다.

대체 인텐트를 테스트하는 방법은 다음과 같습니다.

  1. exerciseObservation 상자에서 aboutExercise 객체를 삭제합니다.
  2. Run App Action을 클릭합니다.

어시스턴트는 마지막으로 완료된 운동의 정보를 표시하는 위젯을 반환해야 합니다.

Google 어시스턴트 플러그인을 통해 마지막으로 기록된 활동을 보여주는 위젯이 있는 화면

7. 다음 단계

수고하셨습니다.

이제 어시스턴트가 지원되는 Android 위젯을 사용하여 사용자의 쿼리를 처리할 수 있습니다.

학습한 내용

이 Codelab을 통해 학습한 내용은 다음과 같습니다.

  • BII에 앱 위젯을 추가합니다.
  • Android Extras의 매개변수에 액세스하도록 위젯을 수정합니다.

다음 단계

이제 피트니스 앱을 추가로 조정해 볼 수 있습니다. 완료된 프로젝트를 참조하려면 GitHub의 기본 저장소를 살펴보세요.

앱 작업을 통해 앱을 확장하는 방법을 보다 자세히 알아보고 싶다면 다음을 확인해 보세요.

Actions on Google 과정을 계속하려면 다음 리소스를 살펴보세요.

트위터에서 @ActionsOnGoogle을 팔로우하여 최신 소식을 확인하고 #appactions로 트윗을 보내 직접 빌드한 결과물을 공유하세요.

의견 설문조사

마지막으로 설문조사를 작성하여 이 Codelab 사용 경험에 관한 의견을 보내주세요.