Sending data from the app to the voice script (Kotlin)

In some cases, you need to send data from your app to the voice assistant to use it in your dialog. For that, you can use Alan’s project API functionality. Project API allows sending any information from the app to the voice script and triggering activities without a voice command. To use it, we need to do the following:

  1. Define a new project API method in the voice script

  2. Call this method from the app

In this tutorial, we will send the information about a list item to the voice script and add it to the favorites list. The user will then be able to ask what items are added to favorites, and the voice assistant will list them.

What you will learn

  • How to send arbitrary data from the voice script to the app

  • How to trigger activities without a voice command

What you will need

For this tutorial, we will use the app created in the Building a voice assistant for an Android Java or Kotlin app tutorial.

Step 1. Add a list of items

First, we need to add a list of items to one of app’s tabs.

  1. Add a new fragment to the app: right-click the app folder and select New > Fragment > Fragment (List). In the displayed window, click Finish.

    ../../../_images/add-list-fragment.png
  2. Open the SectionsPagerAdapter file and update the getItem() function to add the list to the first tab:

    SectionsPagerAdapter
     class SectionsPagerAdapter(private val context: Context, fm: FragmentManager) : FragmentPagerAdapter(fm) {
       ...
       override fun getItem(position: Int): Fragment {
         /// Placing list onto first tab
         return when(position){
           0-> ItemFragment()
           else -> PlaceholderFragment.newInstance(position + 1)
         }
       }
     }
    
  3. Open the MyItemRecyclerViewAdapter file and in the ViewHolder class, register the onClickListener for the item list:

    MyItemRecyclerViewAdapter
     class MyItemRecyclerViewAdapter(private val values: List<PlaceholderItem>) : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {
       ...
       inner class ViewHolder(binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root) {
         ...
         /// Registering click listener
         init {
           itemView.setOnClickListener{v: View ->
             val position: Int = bindingAdapterPosition
             Toast.makeText(itemView.context, "Item # ${position + 1} is added to favorites", Toast.LENGTH_SHORT).show()
           }
         }
       }
     }
    

Run the app. You can now click an item in the list, and the item position will be displayed in the toast message.

Step 2. Define a project API method

To make the favorites list, let’s get the item position, send it to the voice script and add it to the favorites array on the script side when an item is clicked.

In Alan Studio, add the following code to the voice script:

Voice script
 onCreateUser(p => p.userData.favorites = []);

 projectAPI.getPosition = function(p, params, callback) {
     p.userData.favorites.push(params.pos);
     callback();
 }

 intent('What are my favorites?', p => {
     p.play('You have added the following items to favorites');
     for (let i = 0; i < p.userData.favorites.length; i++) {
         let itemPosition = p.userData.favorites[i]
         p.play(`Item ${itemPosition + 1}`);
     }
 });

Here, when the user starts a dialog with the voice assistant, we are first creating an empty favorites array. For that, we are using Alan’s onCreateUser predefined callback.

Next, we are defining the getPosition() project API method that gets the item position and pushes it to the favorites array. And finally, we are adding an intent to check the favorites list contents.

Step 3. Call the project API method in the app

After we have defined the method in the voice script, we need to call it in the app.

  1. In the IDE, open the MainActivity.kt file and add the callProjectApi() function to the MainActivity class.

    MainActivity.kt
     class MainActivity : AppCompatActivity() {
       ...
       /// Calling projectAPI.getPosition from Alan Studio script
       fun callProjectApi(itemPosition: Int) {
    
         /// Providing item position
         val params = JSONObject()
         try {
           params.put("pos", itemPosition)
         } catch (e: JSONException) {
           e.message?.let { Log.e("AlanButton", it) }
         }
         alanButton?.callProjectApi("script::getPosition", params.toString())
       }
     }
    

    Here, we are using the callProjectApi() method to call the getPosition() method added to the voice script.

  2. Open the MyItemRecyclerViewAdapter file and update the onClickListener to call the callProjectApi() function from the MainActivity:

    MyItemRecyclerViewAdapter
     class MyItemRecyclerViewAdapter(private val values: List<PlaceholderItem>) : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {
       ...
       inner class ViewHolder(binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root) {
         ...
         /// Registering the click listener
         init {
           itemView.setOnClickListener{v: View ->
             val position: Int = bindingAdapterPosition
             Toast.makeText(itemView.context, "Item # ${position + 1} is added to favorites", Toast.LENGTH_SHORT).show()
             /// Calling the callProjectApi() function
             val activity = contentView.context as Activity
             (activity as MainActivity).callProjectApi(position)
           }
         }
       }
     }
    

You can test it: run the app and tap several items in the list. Then tap the Alan button and ask: What are my favorites? The voice assistant will list all items you have tapped.