Broadcast Hub

In this tutorial, you'll write an app that automatically responds to texts messages and broadcasts texts messages it receives to a list of phone numbers.The app is inspired by FrontLineSMS, a tool that has been used in developing countries to monitor elections, broadcast weather changes, and in general connect people that don't have access to the web but do have phones and mobile connectivity.

FrontllineSMS is software that runs on a computer with a phone plugged into it. The computer and plugged-in phone serve as a hub for SMS text communication amongst a group. You'll write a version of the software that runs on an Android phone, thus allowing the hub to be as mobile as the phones it connects.

This tutorial assumes you are familiar with the basics of App Inventor-- using the Component Designer to build a user interface, and using the Blocks Editor to specify event-handlers. If you are not familiar with the basics, try stepping through some of the basic tutorials before continuing.

The tutorial also assumes you have completed the TextGroup tutorial and thus are familiar with the basics of the Texting component.

Getting Started

Connect to the App Inventor web site and start a new project. Name it BroadcastHub, and also set the screen's Title to BroadcastHub. Open the Blocks Editor and connect to the phone.

Introduction

BroadcastHub processes text messages that are received in the following manner:

  • If the text message is from an unknown source, the app responds with a text that invites that source to join the broadcast list.
  • If the text message “joinabc” is received, the app adds the sender to the broadcast list
  • If the text message is from a number already in the broadcast list, the message is broadcast to all numbers in the list.

The tutorial covers the following App Inventor concepts:

  • The Texting component for sending texts and processing received texts.
  • List variables to keep track of the numbers to text.
  • The foreach block that allows an app to repeat operations on a list of data (the list of phone numbers)

Setting up the Components

BroadcasterHub facilitates communication between mobile phones. Those phones need not have the BroadcasterHub app installed, or even be smart phones. The app is the hub, and the app's user interface is only for the administrator of the communications network.

For this sample, that user interface is simple: it will display the current broadcast list-- the list of phone numbers which have registered for the service-- and it will report all texts it receives and broadcasts.

To build the interface, add the following components:

Component Type Palette Group What you'll name it Purpose of Component
Label Basic BroadcsastListLabel This will display the phone numbers that are registered
Label Basic
LogLabel This will display a log of the texts received and broadcast
Texting Social
Texting1 The component that processes the texts
TinyDB Basic TinyDB1 To store the list of registered phone numbers
  • Set the Width of each of the labels to Fill Parent so that they span the phone horizontally. Set the Height for the labels to 200 pixels.
  • Set the Text property of BroadcastListLabel to "Broadcast List...".
  • Set the Text property of LogLabel to blank.

BroadcastHub should look like this after its front-end is designed:

Add behaviors to the components

The activity for Broadcast Hub is not triggered by the user entering information or clicking a button, but by texts being received from outside sources. You'll need the following behaviors:

  • When the text message is from an unknown source, the app responds with a text that invites that source to join the broadcast list.
  • When the text message "joinabc" is received, register the sender as part of the broadcast list.
  • When the text message is from a number already in the broadcast list, the message is broadcast to all numbers in the list.

Start by creating the first behavior-- when you receive a text, send a message back to the sender inviting them to text a code, "joinabc", in order to register for the group. You'll need the following blocks:

Block Type Drawer Purpose
Texting1.MessageReceived Texting1
event-handler triggered when the phone receives a text
set Texting1.PhoneNumber to Texting1 to set the number for the return text
value number My Definitions argument of MessageReceived, it is the phone number of sender
set Texting1.Message Texting1 to set the invite message to send
text Text the invite message
Texting1.SendMessage Texting1 send it!

The blocks should look like this:


How the Blocks Work

Texting1.MessageReceived is triggered when any text message is received on the phone. The blocks within the event-handler set the PhoneNumber and Message of the Texting1 component, then send the message

Test the behavior. You'll need another phone besides the one on which the app resides. From the second phone, send a text "hello" to the phone running the app. The second phone should receive a text that invites them to the group.

Handling the "joinabc" text message

Create the blocks for the second behavior: "when the text message "joinabc" is received, add the sender to the broadcast list." First, you'll need to define a list variable, BroadcastList, to store the phone numbers that register. From Definitions, drag out a def var block and name it "BroadcastList". Initialize it with a make a list block from Lists:

Next, modify the Texting1.MessageReceived event-handler so that it adds the sender's phone number to the BroadcastList if the message received is "joinabc". After you add the number to the list, display the new list in the BroadcastListLabel. You'll need the following blocks:

 Block Type
Drawer
Purpose
ifelse
Control
depending on message received, you'll do different things
= block Math the test will be: is messageText equal to "joinabc"
value messageText My Definitions plug into = block
text ("joinabc") Text plug into = block
add items to list Lists to add the sender's number to BroadcastList
BroadcastList My Definitions the list
value number My Definitions plug in as item of add items to list
set BroadcastListLabel.Text to BroadcastListLabel display the new list
BroadcastList My Definitions plug in to set BroadcastListLabel.Text to block
set Texting1.Message to Texting prepare Texting1 to send message back to sender
text ("congrats, you ...") Text congratulate sender for joining group

The blocks should look like this:

How the Blocks Work

The first row of blocks sets Texting1.PhoneNumber to the phone number of the message that was just received. The app then asks if the messageText was of the special code "joinabc". If so, the sender's phone number is added to the BroadcastList, and a congratulations message is sent. If the messageText is something other than "joinabc", the reply message is just the invitation message from before. After the ifelse block, the reply message is sent (bottom row).

Test this behavior. From a second phone, send the text message "joinabc" to the phone on which the app is running. Do you recieve the correct reply? Try sending a different text message as well to check if the ifelse is working correctly.

Broadcasting Messages

Next, you'll add the behavior so that the app broadcasts messages to the numbers in BroadcastList, if the message arrives from a number in BroadcastList. You'll need an additional ifelse block to check if the number is in the list, and a foreach block to send broadcast the message to each item in the list. Here are all the blocks you'll need:

Block Type Drawer Purpose
ifelse Control depending on whether sender is already in list, you'll do different things
is in list? Lists checks to see if something is in a list
global BroadcastList My Definitions plug into list slot of is in list?
value number My Definitions plug into thing slot of is in list?
foreach Control to repeatedly send out message to all in list
global BroadcastList My Definitions plug into list slot of foreach
set Texting1.Message to Texting1 to set the message
value messageText My Definitions the message that was received and to be broadcast
set Texting1.Number to Texting1 to set the phone number
value var My Definitions holds the current item of the BroadcastList, its a (phone) number

The blocks should look like this:

How the Blocks Work

The behavior is complex enough that it requires a "nested" ifelse block. If the phone number of the received message is already in the list, the foreach block is executed and the message relayed to all in the list. If the number is not in the list, the outer else-do clause is executed, and it asks another question, which is the test of the nested ifelse block: is the messageText equal to "joinabc". The app then branches one of two ways based on the answer.

In general, if and ifelse blocks can be nested to arbitrary levels, giving you the power to program arbitrarily complex behaviors.

Test this behavior. First, have two different phones register with the app by texting "joinabc" to the phone which is running the app.Then text another message from one of the phones. Both phones should receive the text.

Logging the broadcasted texts

When a text is received and broadcast out to the other phones, the app should log that occurrence to the app so the administrator can monitor the activity. Earlier, you added the label LogLabel to the user interface for this purpose. Now, you'll code some blocks that change LogLabel each time a new text arrives.

You need to build a text that says something like "message from 111-2222 broadcast". The 111-2222 is not fixed data, but is the value of the variable number that comes with the MessageReceived event. So to build the text, you'll concatenate the first part "message from" with the variable number and finally with the last part of the message, the text "broadcast".

There are two functions in the Text drawer to build text. One is the join function, which joins two pieces of text. Another function, make text, is also available and more convenient to use than join when you have more than two parts. You'll use it for this behavior. Here are all the blocks you'll need:

Block Type Drawer Purpose
set LogLabel.Text to LogLabel display the log here
make text Text build a text object out of multiple parts
text ("message from") Text report message
value number My Definitions the number of sender
text ("broadcast\n") Text text is "message from 111-2222 broadcast" with newline
LogLabel.Text LogLabel add new log to the previous ones

The blocks should look like this:

How the Blocks Work

After broadcasting the message to all the numbers in BroadcastList, the app now modifies the LogLabel to include a report of the just broadcasted text. If the sender's number (value number) is "1112222", then the make text will build the text object:

message from: 1112222 broadcast

along with the log reports that were already in LogLabel.Text from previously received texts. The "\n" is the newline character that causes the old reports to be displayed on the next line, e.g.,

message from: 1112222 broadcast
message from: 555-6666 broadcast

Storing the BroadcastList in a Database

As is, the app works, but every time you close the app the BroadcastList will be lost and everyone would have to re-register. To fix this, you'll use the TinyDB component to store and retrieve the BroadcastList to and from a database. TinyDB allows you to store data persistently-- even if the app is closed, the next time you open the app the data will be there.

The general scheme for storing data persistently is the following: When the app begins, load the list from the database into a variable (e.g., BroadcastList). Then, each time a new item is added to the list, update the database version of the list.

Start by coding the blocks to store the list in the database. With the TinyDB component, a tag is used to identify the data and distinguish it from other data stored in the database. In this case, you can tag the data as "broadcastList". Do the following:
  1. Drag out a TinyDB1.StoreValue block from the TinyDB1 drawer.
  2. Create a text block and give it the text "broadcastList". Place this text block as the tag of StoreValue.
  3. Drag out a reference to BroadcastList from My Definitions. Place it as the value argument of StoreValue.
  4. Place the StoreValue block right below the blocks that add an item to the BroadcastList.

The bottom part of the modified Texting1.MessageReceived event-handler should look like the following:

How the Blocks Work

TinyDB1.StoreValue stores the data in BroadcastList to a database with a tag that you can later use to retrieve the data into your app. In this case, the tag is the text, "broadcastList", and he value is the actual list BroadcastList.

Loading the BroadcastList from a Database

Now add the blocks for loading the list back in each time the app begins. When the app begins, the Screen1.Initialize event is triggered, so your blocks will go in that event-handler. You’ll call TinyDB.GetValue, using the same tag you used to store the list (“broadcastList”). Check if the returned value is a list, because it won’t be if there isn’t any data in the list yet.

The blocks should look like:

How the Blocks Work

The blocks first define a variable, valueFromDB, which is used to temporarily store the data returned from the database. When the app begins, the Screen1.Initialize event is triggered. TinyDB.GetValue is called, and the data from the database is placed in valueFromDB.

The variable is then checked to see if it is a list. If it is not, that means there was no data for the tag “broadcastList” in the database, and an empty text has been returned. This will happen the first time a user opens the app.

If valueFromDB is a list, the list is placed into the variable BroadcastList and the list is displayed.

Test this behavior. Choose Restart App which will trigger the Screen.Initialize. Do the numbers registered earlier appear?

Display BroadcastList with each number on separate lines

Create a procedure displayBroadcastList, which displays the list with each phone number on a separate line. Be sure and call the procedure from below the add items to list block so that the updated list is displayed.

For help displaying the list on separate lines, see Displaying a List

You'll need the following blocks:

Block Type Drawer Purpose
procedure ("displayBroadcastList") Definitions create the procedure
set BroadcastListLabel.Text to BroadcastListLabel display the list here
text ("Phone Numbers...") Text the header for the list
foreach Control iterate through the numbers
name pnumber in the foreach name the foreach variable "pnumber'. This is the current item of the foreach
BroadcastList My Definitions plug into in list slot of foreach
set BroadcastListLabel.Text to BroadcastListLabel modify with each of the numbers
make text Text build a text object from multiple parts
BroadcastListLabel.Text BroadcastListLabel add to the label on each iteration of foreach
text ("\n") Text newline character so that next number is on next line
value pnumber My Definitions the current number from the list

The displayBroadcastList procedure should look like this:

How the Blocks Work

The foreach in displayBroadcastList successively adds a phone number to the end of the label, placing a newline character in between each item.

Of course this procedure will not do anything unless you call it: you should add two calls to the procedure: one within the Texting1.MessageReceived event-handler, and one within the Screen1.Initialize event-handler. The call displayBroadcastList block can be found in My Definitions, and it should replace the blocks that directly set the BroadcastListLabel.Text to the list. You can see how these calls to displayBroadcastList should look in the snapshot of the final version below.

Test this behavior. Try adding some more phone numbers to the list. Do the registered phone numbers now appear on separate lines?

Broadcast Hub, Final Version

Variations

Once you get the Broadcast Hub app working, you might want to explore some variations. For example,

  • Allow client phones to remove themselves from the list by texting "quitabc" to the app.
  • Let the hub administrator (the user of your app) add and remove numbers from the broadcast list.
  • Let the hub administrator specify numbers that should not be allowed into the list.

Review

Here are some of the ideas covered in this tutorial:
  • Apps can react to events, like a text being received, that are not initiated by the user of the app.
  • Nested ifelse and foreach blocks can be used to code complex behaviors.
  • The make text block can be used to build a text object out of multiple parts.
  • TinyDB can be used to store and retrieve data from a database. A general scheme is to call StoreValue to update the database whenever the data changes, and call GetValue to retrieve the database data when the app begins.

Scan the Sample App to your Phone

Scan the following barcode onto your phone to install and run the sample app.

Download Source Code

If you'd like to work with this sample in App Inventor, download the source code to your computer, then open App Inventor, go to the My Projects page, and choose More Actions | Upload Source.
Google is grateful to Professor David Wolber, CS Professor at The University of San Francisco, for developing this tutorial.