Mengintegrasikan Action Aplikasi dengan widget Android

Gambar 1. Meluncurkan widget untuk GET_EXERCISE_OBSERVATION.

Untuk banyak intent, respons terbaiknya adalah memberikan jawaban sederhana, konfirmasi singkat, atau pengalaman interaktif cepat kepada pengguna. Anda dapat menampilkan widget aplikasi Android di Asisten Google untuk memenuhi jenis intent ini.

Panduan ini membahas cara memenuhi kueri pengguna Asisten menggunakan widget, dan cara meningkatkan pengalaman widget untuk Asisten dengan library Ekstensi Widget Action Aplikasi.

Manfaat

Widget adalah tampilan aplikasi mini yang dapat disematkan di platform Android, seperti peluncur atau layar kunci. Dengan Action Aplikasi, Anda meningkatkan dampak widget dengan membuatnya memenuhi syarat untuk ditampilkan di Asisten:

  1. Penemuan: Menampilkan widget secara proaktif sebagai respons terhadap kueri bahasa alami pengguna.
  2. Interaksi: Menampilkan widget dalam konteks handsfree, seperti saat Asisten memberikanhasil personal di layar kunci, dan di Android Auto.
  3. Retensi: Memungkinkan pengguna menyematkan widget yang ditampilkan di Asisten ke peluncurnya. Penyematan fungsi memerlukan library Ekstensi Widget.

Cara Asisten menampilkan widget

Ada dua cara bagi pengguna untuk mengaktifkan widget di Asisten:

  • Meminta widget secara eksplisit berdasarkan nama, atau
  • Mengucapkan kueri ke Asisten yang memicu intent bawaan (BII) atau intent kustom yang dikonfigurasi untuk fulfillment widget.

Panggilan eksplisit

Untuk memanggil widget secara eksplisit untuk aplikasi terinstal apa pun, pengguna dapat menanyakan hal-hal kepada Asisten seperti:

  • "Ok Google, tampilkan widget ExampleApp".
  • "Widget dari ExampleApp".

Asisten menampilkan widget ini dengan pengantar generik: "ExampleApp berkata, ini widget-nya". Meskipun Asisten menampilkan widget yang diminta dengan cara ini secara mudah dari developer aplikasi, metode pemanggilan ini mengharuskan pengguna memiliki pengetahuan eksplisit tentang widget yang akan diminta. Untuk menyederhanakan penemuan widget, gunakan metode fulfillment intent yang dijelaskan di bagian berikut.

Fulfillment intent

Buat widget Anda lebih mudah ditemukan dengan menggunakannya untuk memenuhi kueri bahasa alami yang dilakukan pengguna di Asisten. Misalnya, Anda dapat menampilkan widget setiap kali pengguna memicu GET_EXERCISE_OBSERVATION BII di aplikasi kebugaran dengan bertanya, "Ok Google, berapa mil yang harus saya tempuh minggu ini di ExampleApp?" Selain menyederhanakan penemuan, mengintegrasikan widget dengan Action Aplikasi menawarkan keuntungan berikut:

  • Akses parameter: Asisten memberikan parameter intent yang diekstrak dari kueri pengguna ke widget Anda, memungkinkan respons yang disesuaikan.
  • Pengantar TTS kustom: Anda dapat memberikan string text-to-speech (TTS) untuk diumumkan Asisten saat menampilkan widget.
  • Penyematan widget: Asisten menampilkan tombol Tambahkan widget ini di dekat widget Anda, yang memungkinkan pengguna menyematkan widget Anda ke peluncurnya dengan mudah.

Pengantar TTS kustom dan penyematan widget memerlukan penambahan library Ekstensi Widget ke project Anda.

Mengimplementasikan Widget

Untuk menerapkan fulfillment widget untuk intent Anda, ikuti langkah-langkah berikut:

  1. Terapkan widget Android dengan mengikuti langkah-langkah yang dijelaskan dalam Membuat widget sederhana.
  2. Di file resource shortcuts.xml aplikasi Anda, tambahkan elemen <app-widget> ke kemampuan yang berisi detail fulfillment dan tag BII <parameter>. Update widget Anda untuk menangani parameter.
  3. (Direkomendasikan) Tambahkan library Ekstensi Widget opsional ke project Android Anda untuk mengaktifkan pengantar TTS kustom dan penyematan widget.

Bagian berikut menjelaskan skema <app-widget> untuk shortcuts.xml.

Skema widget

Elemen <app-widget> ditentukan sebagai fulfillment dalam elemen <capability> di shortcuts.xml. Atribut ini memerlukan atribut berikut, kecuali jika dinyatakan sebagai opsional:

Tag shortcuts.xmlAda dalamAtribut
<app-widget> <capability>
  • android:identifier
  • android:targetClass
<parameter> <app-widget>
<extra> <app-widget>
  • android:name (hanya berlaku untuk TTS)
  • android:value (opsional)

Deskripsi skema widget

<app-widget>

Elemen fulfillment widget tingkat atas.

Atribut:

  • android:identifier: ID unik untuk fulfillment ini. Nilai ini harus unik di seluruh elemen fulfillment <app-widget> dan <intent> yang ditentukan dalam <capability>.
  • android:targetClass: Nama class lengkap AppWidgetProvider untuk menangani intent.

<parameter>

Memetakan parameter BII ke nilai <parameter> intent. Anda dapat menentukan nol atau beberapa parameter untuk setiap elemen <app-widget>. Selama fulfillment, Asisten meneruskan parameter dengan mengupdate tambahan untuk instance widget sebagai key-value pair dengan format berikut:

  • Kunci: android:key yang ditentukan untuk parameter.
  • Nilai: Nilai yang diekstrak BII dari input suara pengguna.

Anda mengakses tambahan ini dengan memanggil getAppWidgetOptions() pada objek AppWidgetManager terkait yang menampilkan Bundle yang berisi nama yang memicu BII dan parameternya. Lihat bagian Mengekstrak parameter value untuk mengetahui detailnya.

Untuk informasi lebih lanjut tentang pencocokan parameter BII, lihat Data dan pencocokan parameter.

<extra>

Tag opsional yang mendeklarasikan bahwa pengantar TTS kustom harus digunakan untuk widget ini. Tag ini memerlukan nilai atribut berikut:

  • android:name: "hasTts"
  • android:value: "true"

Kode contoh

XML berikut menunjukkan konfigurasi fulfillment widget untuk kemampuan BII GET_EXERCISE_OBSERVATION:

shortcuts.xml

<capability android:name="actions.intent.GET_EXERCISE_OBSERVATION">
  <app-widget
    android:identifier="GET_EXERCISE_OBSERVATION_1"
    android:targetClass="com.exampleapp.providers.exampleAppWidgetProvider"
    android:targetPackage="com.exampleapp">
    <parameter
      android:name="exerciseObservation.aboutExercise.name"
      android:key="exercisename">
    </parameter>
    <extra android:name="hasTts" android:value="true"/>
  </app-widget>
</capability>

Anda dapat menentukan beberapa elemen <app-widget> atau menggunakan kombinasi elemen <app-widget> dan <intent> per kemampuan. Pendekatan ini memungkinkan Anda memberikan pengalaman yang disesuaikan berdasarkan berbagai kombinasi parameter yang diberikan oleh pengguna. Misalnya, jika pengguna tidak menentukan lokasi penjemputan dalam kuerinya, Anda dapat mengarahkan mereka ke aktivitas di aplikasi Anda yang menampilkan opsi untuk menetapkan lokasi penjemputan dan penurunan. Lihat bagian Intent penggantian untuk informasi selengkapnya tentang cara menentukan intent penggantian.

Mengekstrak parameter value

Pada contoh class AppWidgetProvider berikut, fungsi pribadi updateAppWidget() digunakan untuk mengekstrak nama dan parameter BII dari opsi widget Bundle:

Kotlin

package com.example.exampleapp

//... Other module imports
import com.google.assistant.appactions.widgets.AppActionsWidgetExtension

/**
 * Implementation of App Widget functionality.
 */
class MyAppWidget : AppWidgetProvider() {
    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray
    ) {
        // There may be multiple widgets active, so update all of them
        for (appWidgetId in appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId)
        }
    }

    private fun updateAppWidget(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetId: Int
    ) {
        val widgetText: CharSequence = context.getString(R.string.appwidget_text)

        // Construct the RemoteViews object
        val views = RemoteViews(context.packageName, R.layout.my_app_widget)
        views.setTextViewText(R.id.appwidget_text, widgetText)

        // Extract the name and parameters of the BII from the widget options.
        val optionsBundle = appWidgetManager.getAppWidgetOptions(appWidgetId)
        val bii = optionsBundle.getString(AppActionsWidgetExtension.EXTRA_APP_ACTIONS_BII) // "actions.intent.CREATE_TAXI_RESERVATION"
        val params = optionsBundle.getBundle(AppActionsWidgetExtension.EXTRA_APP_ACTIONS_PARAMS)
        if (params != null && params.containsKey("dropoff")) {
            val dropoffLocation = params.getString("dropoff")
            // Build your RemoteViews with the extracted BII parameter
            // ...
        }
        appWidgetManager.updateAppWidget(appWidgetId, views)
    }
}

Java

package com.example.exampleapp;

//... Other module imports
import com.google.assistant.appactions.widgets.AppActionsWidgetExtension;

/**
 * Implementation of App Widget functionality.
 */
public class MyAppWidget extends AppWidgetProvider {

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // There may be multiple widgets active, so update all of them
        for (int appWidgetId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId);
        }
    }

    private static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {

        CharSequence widgetText = context.getString(R.string.appwidget_text);

        // Construct the RemoteViews object
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_app_widget);
        views.setTextViewText(R.id.appwidget_text, widgetText);

        // Extract the name and parameters of the BII from the widget options.
        Bundle optionsBundle = appWidgetManager.getAppWidgetOptions(appWidgetId);
        String bii =
                optionsBundle.getString(AppActionsWidgetExtension.EXTRA_APP_ACTIONS_BII); // "actions.intent.CREATE_TAXI_RESERVATION"
        Bundle params =
                optionsBundle.getBundle(AppActionsWidgetExtension.EXTRA_APP_ACTIONS_PARAMS);

        if (params != null && params.containsKey(("dropoff"))){
            String dropoffLocation = params.getString("dropoff");
            // Build your RemoteViews with the extracted BII parameter
            // ...
        }

        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
}

Library Ekstensi Widget

Library Ekstensi Widget Action Aplikasi meningkatkan (kualitas) widget Anda untuk pengalaman Asisten Voice-forward. Library Maven ini memungkinkan Anda menyediakan intro text-to-speech (TTS) kustom untuk setiap widget, yang memungkinkan Asisten mengumumkan ringkasan konten yang dirender secara visual kepada pengguna. Ini juga mengaktifkan penyematan peluncur, yang memudahkan pengguna untuk menyimpan widget yang ditampilkan di Asisten ke layar peluncur mereka.

Mulai dengan menambahkan library ke bagian dependensi file build.gradle untuk modul aplikasi Anda:

app/build.gradle

dependencies {
    //...
    implementation "com.google.assistant.appactions:widgets:0.0.1"
}

Pengantar kustom

Setelah mengimpor library Ekstensi Widget, Anda dapat memberikan pengantar TTS kustom untuk widget Anda. Untuk menambahkan definisi Anda ke AppWidgetProvider widget, buka class di IDE dan impor library Ekstensi Widget:

Kotlin

import com.google.assistant.appactions.widgets.AppActionsWidgetExtension

Java

import com.google.assistant.appactions.widgets.AppActionsWidgetExtension;
Selanjutnya, gunakan library untuk menentukan string pengantar dan mengupdate widget:
ExampleAppWidget

Kotlin

package com.example.exampleapp

//... Other module imports
import com.google.assistant.appactions.widgets.AppActionsWidgetExtension

/**
 * Implementation of App Widget functionality.
 */
object MyAppWidget : AppWidgetProvider() {
    fun updateAppWidget(
        context: Context?,
        appWidgetManager: AppWidgetManager,
        appWidgetId: Int
    ) {
        val appActionsWidgetExtension = AppActionsWidgetExtension.newBuilder(appWidgetManager)
            .setResponseSpeech("Hello world") // TTS to be played back to the user.
            .setResponseText("Hello world!") // Response text to be displayed in Assistant.
            .build()

        // Update widget with TTS.
        appActionsWidgetExtension.updateWidget(appWidgetId)

        // Update widget UI.
        appWidgetManager.updateAppWidget(appWidgetId, views)
    }
}

Java

package com.example.exampleapp;

//... Other module imports
import com.google.assistant.appactions.widgets.AppActionsWidgetExtension;

/**
 * Implementation of App Widget functionality.
 */
public class MyAppWidget extends AppWidgetProvider {

  static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
    int appWidgetId) {

    AppActionsWidgetExtension appActionsWidgetExtension = AppActionsWidgetExtension.newBuilder(appWidgetManager)
      .setResponseSpeech("Hello world")  // TTS to be played back to the user.
      .setResponseText("Hello world!")  // Response text to be displayed in Assistant.
      .build();

      // Update widget with TTS.
      appActionsWidgetExtension.updateWidget(appWidgetId);

      // Update widget UI.
      appWidgetManager.updateAppWidget(appWidgetId, views);
    }

}

Penyematan peluncur

Library ini memungkinkan tombol Tambahkan widget ini untuk ditampilkan dengan widget Anda di Asisten. Penyematan memerlukan penambahan definisi penerima berikut ke AndroidManifest.xml:

AndroidManifest.xml

<application>
  <receiver android:name="com.google.assistant.appactions.widgets.pinappwidget.PinAppWidgetBroadcastReceiver"
    android:exported="false">
    <intent-filter>
      <action android:name="com.google.assistant.appactions.widgets.COMPLETE_PIN_APP_WIDGET" />
    </intent-filter>
  </receiver>
  <service
    android:name=
    "com.google.assistant.appactions.widgets.pinappwidget.PinAppWidgetService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
      <action
        android:name="com.google.assistant.appactions.widgets.PIN_APP_WIDGET" />
    </intent-filter>
  </service>
</application>

Ketersediaan inventaris

BII yang mendukung inventaris inline atau inventaris web dapat memperluas inventaris ini ke fulfillment widget Anda.

Inventaris inline

Contoh kode berikut menunjukkan kemampuan BII START_EXERCISE yang dikonfigurasi untuk inventaris inline dan fulfillment widget:

shortcuts.xml

<capability
  android:name="actions.intent.START_EXERCISE">
  <app-widget
    android:identifier="START_EXERCISE_1"
    android:targetClass="com.example.exampleapp.StartExerciseAppWidgetProvider">
    <parameter
      android:name="exercise.name"
      android:key="exerciseName"
      app:shortcutMatchRequired="true">
    </parameter>
  </app-widget>
</capability>

<shortcut android:shortcutId="RunningShortcut">
  <intent
    android:action="android.intent.action.VIEW"
    android:targetClass="com.example.exampleapp.StartExcerciseActivity" />
  <capability-binding
    android:capability="actions.intent.START_EXERCISE"
    android:parameter="exercise.name"
    android:value="running;runs" />
</shortcut>

Pada contoh sebelumnya, saat pengguna memicu kemampuan ini dengan meminta Asisten, “Mulai jalankan dengan ExampleApp”, paket opsi untuk fulfillment <app-widget> akan berisi key-value pair berikut:

  • Key = “exerciseName”
  • Value = “RunningShortcut”

Inventaris web

Lihat kode contoh berikut untuk kemampuan yang diaktifkan untuk inventaris web dan fulfillment widget:

shortcuts.xml

<shortcuts>
  <capability
    android:name="actions.intent.START_EXERCISE">
    <app-widget
      android:identifier="START_EXERCISE_1"
      android:targetClass="com.example.exampleapp.CreateTaxiAppWidgetProvider">
      <parameter
        android:name="exercise.name"
        android:key="exerciseName"
        android:mimeType="text/*">
        <data android:pathPattern="https://exampleapp.com/exercise/.*" />
      </parameter>
    </app-widget>
  </capability>
</shortcuts>

Pengujian

Gunakan Alat Uji Action Aplikasi, fitur dari plugin Asisten Google untuk Android Studio, untuk menguji widget pada perangkat fisik atau virtual. Untuk menggunakan alat ini, ikuti langkah-langkah berikut:

  1. Hubungkan perangkat pengujian dengan aplikasi yang sedang berjalan.
  2. Di Android Studio, buka Tools > App Actions > App Actions Test Tool.
  3. Klik Create preview.
  4. Di Android Studio, jalankan aplikasi Anda di perangkat pengujian.
  5. Gunakan aplikasi Asisten di perangkat pengujian untuk menguji Action Aplikasi Anda. Misalnya, Anda dapat mengucapkan sesuatu seperti "Ok Google, berapa mil yang telah saya tempuh minggu ini di ExampleApp?".
  6. Amati perilaku aplikasi Anda, atau gunakan debugger Android Studio, untuk memverifikasi hasil tindakan yang diinginkan.

Pedoman kualitas

Bagian ini memperjelas persyaratan utama dan praktik terbaik saat Anda mengintegrasikan Action Aplikasi dengan widget.

Konten dalam widget

  • (Wajib) Jangan tampilkan iklan di widget Anda.
  • Konten widget harus sepenuhnya difokuskan untuk memenuhi intent — jangan mencoba memenuhi beberapa intent dengan satu widget, atau menambahkan konten yang tidak relevan.

Menangani autentikasi

  • (Wajib) Jika autentikasi pengguna diperlukan untuk menyelesaikan alur pengguna, tampilkan widget yang menjelaskan bahwa pengguna perlu melanjutkan penggunaan aplikasi. Autentikasi pengguna inline di Asisten Google tidak didukung untuk Action Aplikasi.
  • Jika pengguna mengizinkan aplikasi Anda menampilkan data melalui widget, Anda dapat menampilkan widget error saat runtime untuk pengguna yang tidak diberi otorisasi.

Intent pengganti

  • (Wajib) Di shortcuts.xml, selalu berikan penggantian <intent> selain fulfillment widget Anda untuk kemampuan tertentu. Intent penggantian adalah elemen <intent> tanpa nilai <parameter> yang diperlukan. Hal ini memungkinkan Asisten untuk memenuhi Action saat kueri pengguna tidak berisi parameter yang diperlukan oleh elemen fulfillment lainnya yang ditentukan dalam kemampuan. Pengecualian untuk hal ini adalah saat tidak ada parameter yang diperlukan untuk kemampuan tersebut, dalam hal ini hanya fulfillment widget yang diperlukan.
  • Intent penggantian akan membuka aplikasi Anda ke layar yang relevan di aplikasi Anda, bukan di layar utama.

Kode contoh berikut menunjukkan <capability> dengan penggantian <intent> yang mendukung fulfillment <app-widget> utama:

shortcuts.xml

<shortcuts>
  <capability
    android:name="actions.intent.CREATE_TAXI_RESERVATION">
    <!-- Widget with required parameter, specified using the "android:required" attribute. -->
    <app-widget
      android:identifier="CREATE_TAXI_RESERVATION_1"
      android:targetClass="com.example.myapplication.CreateTaxiAppWidgetProvider">
      <parameter
        android:name="taxiReservation.dropoffLocation.name"
        android:key="dropoff"
        android:required="true">
      </parameter>
    </app-widget>
    <!-- Fallback intent with no parameters required to successfully execute. -->
    <intent
      android:identifier="CREATE_TAXI_RESERVATION_3"
      android:action="myapplication.intent.CREATE_TAXI_RESERVATION_1"
      android:targetClass="com.example.myapplication.TaxiReservationActivity">
    </intent>
  </capability>
</shortcuts>

Pengungkapan Data Google Play

Bagian ini mencantumkan data pengguna akhir yang dikumpulkan oleh library Ekstensi Widget versi terbaru.

SDK ini mengirimkan respons text-to-speech (TTS) yang diberikan developer yang diumumkan kepada pengguna oleh Asisten Google menggunakan teknologi ucapan Asisten. Informasi ini tidak disimpan oleh Google.

Tindakan aplikasi juga dapat mengumpulkan metadata aplikasi klien untuk tujuan berikut:

  • Untuk memantau berbagai tingkat adopsi versi SDK.
  • Untuk mengukur penggunaan fitur SDK di seluruh aplikasi.