Broadcast Hub extended
For this tutorial I am going to show you a piece of the source for my soon to be released application called "I AM HUB®"
This tutorial assumes that you have completed the Broadcast Hub tutorial on the App Inventor site and we are going to setup a procedure that will take take the received messages and store them to tinydb. This allows your to have a persistent archive of all messaging activity. The way "I AM HUB" is designed, the broadcast messages are not immediately displayed to the admin. Instead, I created a reports page where I call the message archive into it’s own window. This serves a couple purposes. First, it does not fill the screen, until you call it. Second, it does not add additional resource requirements to the device every time a message is sent. Instead it only asks for CPU time when you want to view the archive.
For your interface you will need to setup a few extra blocks and one or two more pages, depending on where you want to place the button to show the archive. Check out my tutorial Creating Multiple Pages if you are not familiar with that process. Tony has a great example of doing a similar thing, but using a tabbed view. You can find the source for his example on the Source Code page of theAIRepository. Look for MultiTabSim.zip under the Samples – Misc folder. In my app, I have a button that takes you to a report page where you find a button that displays the message archive report. How you do this is up to you, but keep reading to see how the actual report is stored and later displayed on request.
When your interface is ready, and you’ve hopefully given your components appropriate names, you’ll need to go to the Blocks Editor to setup the code for this to work. By now you should be familiar with how this process works, so I will not be going through the details of dragging out the blocks and plugging them in. I will just show you the blocks and step through them to explain how they work. Don’t forget, you can click the screenshots below to get a larger view.
These blocks come from the texting component and as you can see there are a few nested controls. When a message arrives it first tests to see if the incoming number is in the global BroadcastList. If the number is NOT (false returned), else-do will be calld and this portion is pretty much the same as in the tutorial except I have my own custom messages.
If the test is positive (true returned), then-do will be called, and here is where I store my message to:
The foreach block takes the received message variable and sends it to every phone number in the global BroadcastList, which is indicated in the "in list" socket. It will step through every number in the list and send the message. After it sends the message it will add the number and the message using join, to my global memMsgLog. The archive isn’t much good with only messages, so I make a clean list that stores them as "number : message" and finally adds them to the database using the MemMsgLogList tag with the value messageText.
Now that I have a stored list, it will persist even after the app is closed. For your screen initialize event, which occurs when the app starts, you need to load the list into memory, so it’s ready to access when called. You can also chose to load it when it’s called instead of when the app starts.
I start by setting the global valueFromDB to call TinyDB1.GetValue, referencing the MemMsgLogList tag. After that I do a quick "if" test to check if the value I just loaded has any data, and if it does, I set my global memMsgLog list to the globalValueFromDB, which in essence loads that list into memorry in my memMsgLog list. At this point I am ready to call this list any time I need to show it. Here is the procedure to accomplish this.
When the user clicks the button to show the list, in my app it’s called Page3ViewMessageLogBtn.Click, they will get a page with the message history. This contents of this page are created as follows. I need to give my app a way of stepping through the list and showing everything in a clean format. I defined a memmsghistIndex and set it to 1. Now I define a procedure MemMsgLogHistory, which is called by my button. This procedure has a couple controls. The first one is very important, as it makes sure that the list I loaded is not empty, or else it will throw an error for trying to handle a null value.
****Correction added December 20th, 2010****
In my procedure I mention checking the list to make sure it’s not empty before trying to act on the results. Well the way I have it setup, I ended up discovering my app had a huge bug, because an empty list still returns a value of "2" as it contains "( )". Huge thanks to Tony at http://www.tAIR.info, for helping me find the correct list function to do this check. Instead of what I have in the above screenshot, the following are the blocks you need to attach to the test socket of the if block.
Using length of list, we can correctly check for actual contents. The difference is that the block I used originally, checks for length. It does not care what the data is, it only cares of something is there or not. In this case we care, so length of list solves that problem, because it looks between the parentheses and returns false if there is nothing there.
If the list is empty, it will simply exit and not show you anything. That’s what we want and an empty space is better then errors. I just thought of a nice feature and I’ll share it with you know as I add it to my app.
If there is no history to display, lets tell the admin that there is nothing to show, instead of just leaving a blank screen. Feedback to your user is very important. You need to make sure proper messaging is setup so that normal behavior does not look like an error. With that, I just added the notifier .ShowAlert block at the end of my "if test" control so that if it does return a false (no data in list) it will exit with the alert, which will pop up the message "No message history to display." Now my user is informed and is not sending emails that my app is not working.
If my initial test returns a true (data exists), then-do will be called and I will set my label MemMsgLogsArchive.Text (this is where I will display the history) to the words "Message Archive:". The "\n" will add a new line. I set my global memmsghistIndex to 1 and call a foreach loop to display everything in my list. Each variable in the list "global memMsgLog" is given the name "histItem" and I change the MemMsgLogsArchive.Text label using a call to "make text". This starts by displaying what’s already in that label, followed by the next item in the list using a clean and nicely formatted view showing 1 item per line. It will look like this:
1) number : message
2) number : message
3) number : message
and so on…
If you recall, I originally stored my message with both the number and the message. Now you see why. If I didn’t, I would only get the message and while it’s something, it really does me no good if I don’t know who sent it. This is finally followed by incrementing my index +1, which then goes to the next item (if one is availale) and starts again from the top of the list.
And there you have it, a complete solution to storing and displaying the message history.
Don’t forget to keep an eye on my site. I will be releasing I AM HUB® Lite Beta soon!