bixby: Audio player, how to give input to audio player - bixby

I have downloaded the sample capsule and implemented into my capsule and it is working, but now i need to pass few ids and generate the content for songs.
So my intent on followup will be
intent{
goal:PlaySongs
value-set:MultipleArtistId{$expr(singleArtistEvent.artistId)}
}
My PlaySongs action file read like this
action (PlaySongs) {
type (Search)
collect {
computed-input (songToPlay) {
description (Create the playlist to play)
type (audioPlayer.AudioInfo)
min (Required) max (One)
compute {
intent {
goal: GetMeArtistSong
value-set: MultipleArtistId
}
}
hidden
}
computed-input (play) {
description (By passing in the AudioInfo object to the PlayAudio action, we ask the client to play our sound.)
type (audioPlayer.Result)
compute {
intent {
goal: audioPlayer.PlayAudio
value: $expr(songToPlay)
}
}
hidden
}
}
output (Result)
}
GetMeArtistSong action file reads like this
action (GetMeArtistSong) {
type(Search)
description (Artist Song)
collect {
input (artistId) {
type (MultipleArtistId)
min (Optional) max (One)
}
}
output (audioPlayer.AudioInfo)
}
I am unable to get the artist id on GetMeArtistSong js file.
What are things i am doing wrong?
And what is hidden for? please explain.

hidden means the linked JS function do not need to list that input as argument. Without hidden, your JS function need to have both songsToPlay and play as argument.
Without the actual JS file and endpoints file, I can only speculate your question about artistId. It should not be related to audio player. Check endpoints and do console.log(), my feeling is that the action model and JS function are not properly linked. Also, you may want to change to min(Required) to enforce an input.

Related

How to access Bixby profile information (first name/last name) inside Input-View

I want to access the user info in the result- and input-view to make a message like that
"Thanks [Username] for you sharing"
I assume result-view is easy, so I include an example here for input-view.
The challenge here is to render the [username] which is not part of the input value. The solution is to group these two values together with an action.
input-view {
match: IntAge(this) {
to-input: GetStructPerson (action)
}
message {
template ("Enter age of #{value(action.name)}")
}
render {
form {
elements {
number-input {
id (that)
label (Age)
type (IntAge)
}
}
on-submit {
goal: IntAge
value: viv.core.FormElement(that)
}
}
}
}
Action is nothing but a constructor
action (GetStructPerson) {
description (__DESCRIPTION__)
type (Constructor)
collect {
input (name) {
type (TextName)
min (Required) max (One)
}
input (age) {
type (IntAge)
min (Required) max (One)
}
}
output (StructPerson)
}
I think this is the similar render result you want.
User information is present in $vivContext which is accessible to the developer in the corresponding javascript file of an Action. One way to achieve what you are trying to do would be to create a hidden property in your structure (called in the result-view) called userName and use an Action FillUserName to populate this property.
The following resources will help too. Good luck!
https://bixbydevelopers.com/dev/docs/dev-guide/developers/actions.js-actions#passing-user-context-information
https://github.com/bixbydevelopers/capsule-samples-collection/tree/master/user-context

How to make Bixby ask input without user

I want to make Bixby ask for input values when the user just states what he/she wants to do(without any valuable input given.)
For example,
user: I want to search something
Bixby: What do you want to search?
user: *possible-input-value*
Is this possible? If so, how can I implement this?
That's easy in Bixby. If you make an input to your action required...it will prompt the user for input. Let's say you have an action like this:
action (FindSomething) {
type(Search)
description (Search for something)
collect {
input (search) {
type (Search)
min (Required) max (One) // Force Bixby to prompt for an input.
}
}
output (viv.core.Text) // some result
}
And you have a search concept defined like this:
name (Search) {
description (Search term)
}
You can provide an input view for the user to enter the term (via screen).
input-view {
match: Search(search)
message {
template ("What do you want to search?")
}
render {
form {
elements {
text-input {
id (search)
label (Search Term)
type (Search)
max-length (50)
value ("#{raw(search)}")
}
}
on-submit {
goal: Search
value: viv.core.FormElement(search)
}
}
}
}
In addition to Pete's response, you need to enable this for voice input (UI only input will not pass capsule review for submission to the marketplace). To do so, you need to create natural language training for Search
Since you are asking for input at a prompt, you need to create a training that will be used when prompting for Search
Training source for this would look like:
[g:Search:prompt] (sample search text)[v:Search]
Or in the UI
Definitely check out the sample code at https://github.com/bixbydevelopers for more examples. A simple example of input would be in https://github.com/bixbydevelopers/capsule-sample-fact - note the training that uses tags
In addition to Pete's response, I would recommend taking a look the design principles for Bixby development. These principles will guide you in making a targeted capsule that solves the use case you would like to address.

Start playing the audio after selecting card in results view

I'm trying to take the data (concept) from a card a user selects from a results view containing multiple cards and instead of presenting the information from that card in a more detailed view i'm trying to use the properties of the Concept the card displays, ie: Song author, title ... and transform that into a audioPlayer.AudioInfo concept and start playing the audio.
I am familiar with how the audio demo capsule plays audio, where the audioPlayer.AudioInfo is first build, an then passed to the audio player in the same action: https://github.com/bixbydevelopers/capsule-samples-collection/tree/master/audio
action (PlaySessionOfDay) {
type (Search)
collect {
computed-input (sessionToPlay) {
description (Fetch the sessions to be played)
type (audioPlayer.AudioInfo)
min (Required) max (One)
compute {
intent {
goal: BuildSessionOfDayAudioInfo
}
}
hidden
}
computed-input (session) {
description (By passing in the AudioInfo object to the PlayAudio action, we ask the client to play our sound.)
type (audioPlayer.Result)
compute {
intent {
goal: audioPlayer.PlayAudio
value: $expr(sessionToPlay)
}
}
hidden
}
}
output (Result)
}
How an can you use the selected Song card from the list of cards as the input into the PlaySessionOfDay action and then pass it to an action like BuildSessionOfDayAudioInfo, to create an audioPlayer.AudioInfo.
It looks like you can't have compute block
compute {
intent {
goal: BuildSessionOfDayAudioInfo
}
}
unless you are using computed-input (sessionToPlay).
Edit: I think some of the trouble is because by default cards clicked on in a list-of (songs) view invoke a details view. Is there any way to avoid this and use the selected data as the input to an action?
Is there any way to avoid this and use the selected data as the input to an action?
Yes, set has-details (false) in your view model, read more here
You need to add on-click with the intend PlaySessionOfDay
You would also need implement PlaySessionOfDay so it could take an input (I assume you have more than one content to play)

How do you confirm a default input for an action in bixby?

I would like to collect an address input for an action "evaluate". Ideally the behavior would be something like this:
1) Evaluate is initiated
2) a default address is pulled from user profile,
user is asked if they would like to use this address
3) if no default address or user does not want to use it,
prompt user for an address
4) Evaluate action runs with either default address or custom input address
What I am thinking of doing is adding 2 constructor actions that could potentially return a geo.Address object, ReturnSelfAddress and GetCustomAddress. ReturnSelfAddress will collect an address from the self library capsule and GetCustomAddress will prompt the user to enter an address as a geo.UnstructuredAddress and convert that into a regular geo.Address.
The input to the Evaluate action is this:
input (address) {
type (geo.Address)
min (Required)
max (One)
default-init {
intent {
goal: ReturnSelfAddress
}
}
}
Then I would have a confirmation view that would confirm ReturnSelfAddress to let the user select that if desired. If ReturnSelfAddress fails, then Evaluate will still look for a geo.Address input. I would have an input-view that would match the geo.Address concept and prompt the user to input a geo.UnstructuredAddress. Something like this (not sure if this is 100% correct):
input-view {
match: geo.Address(this)
message ("What is your street address?")
render{
form {
elements {
text-input {
id (address)
label("Address")
required (true)
type (geo.UnstructuredAddress)
}
}
on-submit {
goal: GetCustomAddress
value: viv.core.FormElement(address)
}
}
}
}
Alternatively, if the user rejects the default, then I will have an on-abort goal of GetCustomAddress that would prompt the user:
on-abort {
intent {
goal: GetCustomAddress
}
}
This seems to be very involved, and I am questioning if there is a feature that i might be missing that will help me get the desired behavior. So i guess i have 2 questions:
1) Before i go too deep down this rabbit hole, will this idea work?
2) Is there a better way to get the desired behavior of "try for default and if none or user rejects, prompt for input"?
You can try the confirmation view, but here is an easier way you might find useful.
Define the input in action model with default-init and prompt-behavior (AlwaysElicitation)
input (email) {
type (TypeTextEmail)
min (Required) max (One)
default-init {
intent {
goal: FetchEmailFromName
value: $expr(name)
}
}
prompt-behavior (AlwaysElicitation)
}
Define input view to overwrite the default if user want to
input-view {
match: TypeTextEmail(this)
render {
form {
elements {
text-input {
id (this)
type (TypeTextEmail)
label ("Email:")
max-length (50)
value ("#{value(this)}")
}
}
on-submit {
goal: TypeTextEmail
value: viv.core.FormElement(this)
}
}
}
}
You can download and try the training example in example.inputview
For confirmation view, please refer the example.shirt on Github

How do I have bixby use app-launch to open google maps?

I am trying to open google maps using the on-click key from a compound card, but I don't know what to include in the payload-URI key for app-launch. The documentation uses the example which is commented out, but I do not know what to fill in for the application(google-maps).
I am getting two errors both being Unknown key message/app-launch.
This is the code we are trying to use, so that when a compound card is clicked, it opens google maps with app-launch.
// PersonSelectionView.view.bxb
input-view {
match: Spot (this)
// optional selection dialog to overwrite any other default dialog
message (Pick a spot)
render {
// used to iterate over the list of candidates
selection-of (this) {
navigation-mode {
read-none {
list-summary ("There are #{size(this)} #{value(categories)} spots near you")
item-selection-question (Which one would you like?)
}
}
where-each (one) {
// you can use conditional logic to control how candidates are displayed,
// using either a standard layout with a match pattern, or a layout macro
compound-card {
content {
map-card {
title-area {
slot1 {
text {
value("#{value (one.spotName)}")
}
}
slot3 {
single-line {
text {
value("#{value (one.distance)} Miles away")
}
}
}
}
aspect-ratio (1:1)
markers {
marker {
geo ("Location.point")
icon {
template (/images/icons/red-marker.png)
}
width (15)
height (20)
anchor-x (5)
anchor-y (15)
rotation (0)
}
}
}
paragraph {
value {
template ("#{raw(description)}")
}
style (Detail_L)
}
}
on-click {
message ("TESTING THIS MESSAGE")
app-launch {
//payload-uri ("bixby://com.android.systemui/DummySystem/punchOut")
}
}
}
}
}
}
}
An "Unknown Key" error means that the key you are trying to define is not one of the valid child keys of the key you are currently in. The reference section of the Bixby Developer Documentation provides each key with its valid child keys.
Both app-launch and message are not child keys of on-click.
app-launch cannot be defined within an on-click. It must be defined in its own result-view.
message can be defined in multiple keys but not on-click
Your on-click would need to redirect to a separate result-view which would contain the app-launch key with the correct payload-uri defined.
You would need the following to implement the behavior you described:
An Action (and backing Action Javascript) to return the URI
A Concept to hold the URI returned by the Action
A result-view with a match that matches the Concept
Example Action:
action (LaunchDefinedUri) {
description (Launches the defined uri)
type (Commit)
collect {
input (launchUri) {
type (LaunchUri)
min (Required) max (One)
}
}
output (LaunchUri)
}
Example Action Javascript:
module.exports = {
function: LaunchDefinedUri
}
function LaunchDefinedUri(launchUri) {
return launchUri
}
Example Concept:
text (LaunchUri) {
description (Uri to be launched)
}
Example Result View:
result-view {
match: LaunchUri(this)
app-launch {
payload-uri("#{value(this)}")
}
render {
nothing
}
}
As for Google Maps API in particular, the Google Maps documentation seems to provide information on how to define the correct URIs for your specific purpose and behavior.
Please look into this official library provided by the Bixby team, which provides punch-out to Google Maps.
https://bixbydevelopers.com/dev/docs/dev-guide/developers/library.navigation

Resources