The bixby.textMessage
library capsule provides a way for your capsule to send text messages. It takes a recipient and phone number as input, and can either take the text of the message from your capsule, asking the user to confirm before sending and change the message if they wish, or prompt the user to enter the message text.
The library can run on devices that are capable of sending SMS messages, and can use the user's Bixby-enabled phone to send the message on some but not all other devices. Devices with mobile
and watch
targets can send messages; fridge
and tv
targets cannot.
Import the capsule in your capsule-imports
block.
A sample capsule demonstrating the bixby.textMessage
library is available as library-text-message-example
in the Bixby Capsule Samples Collection on GitHub.
The bixby.textMessage
and viv.shareVia
library capsules both allow you to share from your capsule, but have different uses.
The bixby.textMessage
library capsule allows your capsule to send a text message to a phone number. For example, if you want to use a hard-coded phone number, such as a customer service number or one for delivery, you can use bixby.textMessage
. However, if you want users to be able to share things, such as an image or video, you should instead use viv.shareVia
, which allows users to choose an app and recipient when sharing.
A sample capsule that uses bixby.textMessage
is available as library-text-message-example
in the Bixby Capsule Samples Collection on GitHub.
The Text Message library provides structure concepts, MessageInfo
and MessageText
, that contain the information necessary to send the message. MessageInfo
also contains a named-consumer
link to the SendMessage
action. A named-consumer
explicitly links a concept to an action, letting capsules refer to the action with notation similar to property projection.
Your capsule should extend both of these concepts:
structure (MessageInfo) {
extends (message.MessageInfo)
}
text (MessageText) {
extends (message.MessageText)
}
Then, define a constructor action that takes a model with a phone number property, an optional recipient name, and optional message text. The action should output a MessageInfo
model.
Here's an example ComposeMessage
action; you should adjust this for your capsule's specific use case. (For instance, if your capsule has a Business
concept with properties for name and phone number, this action should take that as an input rather than the phoneNumber
and recipientName
.)
action (ComposeMessage) {
type (Constructor)
collect {
// phoneNumber and recipientName should be text primitives
input (phoneNumber) {
type (PhoneNumber)
min (Required) max (One)
}
input (recipientName) {
type (BusinessName)
min (Optional) max (One)
}
// if the message text is not provided as an input, the user will be
// prompted to enter the text; if it is provided, the user will be
// asked to confirm sending the message
input (messageText) {
type (MessageText)
min (Optional) max (One)
}
computed-input (message) {
type (message.MessageInfo)
min (Required) max (One)
compute {
intent {
goal: message.ComposeMessage
// if phoneNumber and RecipientName don't extend message.PhoneNumber
// and message.RecipientName, use cast() here
value: $expr(phoneNumber.cast('message.PhoneNumber'))
value: $expr(recipientName.cast('message.RecipientName'))
value: $expr(messageText)
}
}
}
}
output (MessageInfo) {
evaluate {
$expr(message)
}
}
}
Your capsule also needs a SendMessage
action. Assuming your capsule has the proper MessageInfo
concept, you can use this implementation directly.
action (SendMessage) {
type (Search)
collect {
input (messageInfo) {
type (MessageInfo)
min (Required) max (One)
hidden
}
computed-input (actionResult) {
type(message.ActionResult)
min(Optional) max(One)
compute {
intent {
goal: message.SendMessage
value: $expr(messageInfo)
}
}
}
}
output (message.ActionResult) {
evaluate {
$expr(actionResult)
}
}
}
This action sends the message and returns a message.ActionResult
concept. To see whether sending the message was successful, check the result
property of ActionResult
, which is an enum set to one of these values:
success
failure
cancelled
ActionResult
also has a description
property, which contains more information about the failure condition if the result was not success
, and a timeStampInfo
property (of viv.time.DateTime
type).
From anywhere in your capsule, you can use an intent
to send a message. If you don't provide message text, the user will be prompted to enter it.
intent {
goal: SendMessage
route: ComposeMessage
value: PhoneNumber (1-555-666-1212)
// optional
value: RecipientName (Super Burrito)
value: MessageText (I want to sign up for your mailing list)
}
The value
keys should match the input of your ComposeMessage
action. If it takes a structure like a business or a contact as input, the intent could look like this:
intent {
goal: SendMessage
route: ComposeMessage
// where "this" is a contact or a business model
value: $expr(this)
// optional
value: MessageText (I want to sign up for your mailing list)
}
Training entries should use the SendMessage
action as their goal, routing through your capsule's ComposeMessage
action. For instance, your capsule could find a contact using a search term. The Aligned NL for that training entry might be like the following:
[g:SendMessage,r:ComposeMessage] Text (Fred)[v:contact.SearchTerm] the
message (Are you feeling ok?)[v:MessageText]
Your capsule could also implement its own SearchTerm
model to find businesses:
[g:SendMessage,r:ComposeMessage] Send feedback to (Super Burrito)[v:SearchTerm]
If that capsule was displaying a result view for a business, you could add a continuation that lets the user send feedback via text:
[g:SendMessage:continue:Business,r:ComposeMessage] Leave feedback
The following video demonstrates how to use the textMessage
library in your capsule with the library-text-message-example
sample capsule.