Chapter 4: OrderDroid: A Maintainable Mobile Commerce App
In This Chapter
• Creating an application with multiple screens
• Getting data out of your App Inventor application with e-mail
• Using ActivityStarter to start other Android applications
One of the questions App Inventors ask most often is, “How do I get data out of my application?” in this chapter, you build an application that takes user data and e-mails it to a given address. This is a good method for gathering field data and storing it elsewhere. In a later project, you see how to use the TinyWebDB component to get data in and out of your applications. The e-mail method you learn in this project could be used to send data to an e-mail scraping application or be archived in a document management system such as Microsoft’s SharePoint.
The other major limitation of the current App Inventor version is that it has only one Screen1 component and no easy way to create more. In this project, you learn how to create multiple screens for your App Inventor applications. This enables you to have settings screens, multiple output screens, and so on. For the purposes of this book, I call these “imitation” screens VirtualScreens. You can use VirtualScreens whenever you want to create more than one user interface view for your applications.
The method you use to send e-mails in this project uses the ActivityStarter to call the built-in default e-mail handler. The ActivityStarter can be used to call other applications on the Android device. The ActivityStarter requires very specific properties to function correctly.
VirtualScreens are the name I give in this book to the method of “faking” multiple App Inventor screens. The term is used in other applications and other types of programming to mean vastly different things. Future versions of App Inventor will very likely contain a built-in method for creating multiple screens. For the time being, you’ll need to use the method I outline here.
Creating the OrderDroid Application
The OrderDroid application will be used by a salesperson in the field to take a customer’s name, address, and purchase info and e-mail it to a predetermined processing address for fulfillment. An important design qualification is that it be maintainable because you anticipate rapidly expanding usability requirements.
Your design
The design goals for the OrderDroid application are simple statements that contain a great deal of complex algorithm to accomplish. Future versions should not have to be significantly redesigned to add functionality. The design sketch is shown in Figure 4-1.
Figure 4-1: The design sketch for OrderDroid 1.0
The following design goals are your first milestone. When you can check these off, you have reached a performance and functionality point that you could release and use. You will have another set of design goals for the next milestone:
• A form that accepts input of data such as customer name, address, items sold, and payment options
• The ability to e-mail the order to an address for processing
• Easy maintainability
Your primitives
These are the algorithms and logical pieces to accomplish your design goals. Each primitive is built to achieve a piece of an overall completion goal:
• A form to get the customer’s name and address
• A list of products to select for purchase
• A way to select, store, and display a single product selection
• A way to record payment options
• A way to send the complete order via e-mail to a fixed address, while maintaining the possibility of supporting variable addresses in the future
Your progression
This is the a logical way to move through your events, primitives, and design goals. However, remember to be flexible enough to quickly move to a different primitive or goal if the flow is natural and logical.
1. Create the form with the customer name and address input, item selection, payment check boxes, and a button for submitting the order.
2. Create blocks to populate a list of product items.
3. Store selected purchase items in a variable.
4. Create a procedure to e-mail the entire form to a predetermined address.
New components
These are the important new components introduced in this project:
• ActivityStarter
• ListPicker
• CheckBox
• TextBox
• Notifier
New blocks
These are the important new blocks used in this project:
• ActivityStarter.DataUri
• Notifier1.ShowMessageDialog
• Make a List
• Listpicker.AfterPicking
• Make Text
Getting Started on OrderDroid 1.0
The OrderDroid application should be built with maintainability foremost in your mind. Applications frequently go through usability changes after their first release and making changes should not require a complete redesign or major rethinking of your algorithms. Even more importantly, you will very likely want to add capabilities to your applications someday.
One way that developers keep maintainability in their applications is to compartmentalize the functionality. In the last project, you used a procedure to create code that you could reuse for multiple events in your application. In this project, you use procedures again, with a slightly different emphasis for maintainability. Not only will your procedures exist for reusability, but they will be used as expansion and scalability points. In other words, a procedure for e-mailing the form may be not only for reusability but also to isolate the e-mailing logic so it can be expanded on or changed in a later version.
Here’s how to get started on the OrderDroid project:
1. From the My Projects window, start a new project and name it OrderDroid1_0.
2. Drag and drop a new VerticalArrangement onto the viewer from the ScreenArrangements palette.
3. Change the default VerticalArrangement1 name to VirtualScreen1 using the Rename button in the Components column.
For this version of the app, you will only be using a single VirtualScreen. (More on VirtualScreens later.) With your emphasis on maintainability, you want to keep all of version 1.0’s functionality constrained within a single VerticalArrangement so that later you can add other screen arrangements to contain new functionality.
4. Change the VirtualScreen1 Width
property in the Properties column to Fill Parent
.
5. Make the Screen1 component active by selecting it in the Components column. Change the Title
property in the Properties column to OrderDroid 1.0
.
6. Set Screen1
BackgroundColor
to dark gray by clicking the square color picker.
For this application, clarity and usability are of greatest importance. A dark gray background provides a good background for high contrast text without being glaring or too gloomy.
7. Deselect the Screen1 Scrollable
property.
The Scrollable
property is less important in this version, but when you move on to 2.0 and use multiple virtual screens, you need to have the scrollable property off.
8. Drag and drop a label into the VirtualScreen1. Change its name to lblCustomerInfoText
using the Rename button in the Components column.
9. Replace the default text in the Properties column Text
property field with Customer Information
. To increase visibility and contrast, change the text color of labCustomerInfoText
to white
. This label is static and acts as an identifier for the content of the form below it.
10. Drag a text box from the Basic palette and drop it below Customer information label in VirtualScreen1. Text boxes allow you to capture user text input and then process or use it.
Text boxes are the primary way you get information from your application user.
For our OrderDroid application, text boxes are important because you are creating a form that is filled out and submitted via e-mail. Remember that naming your components with easy-to-read names that specify their purpose makes building the blocks much easier. Good naming conventions also help with our overarching goal of maintainability. In large-scale developments, more than one developer may well be working on the same code. Easily understood names help everyone debug and maintain code.
11. Rename the TextBox1 component txtCustomerName
using the Rename button in the Components column. Set the Width
property to Fill
Parent
.
Note the txt
prefix at the beginning of the component name. I use the txt
prefix to denote text entry boxes throughout this book.
12. In the Properties column, change the Width
property to Fill Parent
. You should see the text box fill out to the width of your screen on your connected Android phone. Change the Hint
property to Enter customer’s name
.
Hint text is very useful for saving space and letting your user know what to enter into a text box. Adding a label for every text element in our form takes a lot of screen space. Instead, use the Hint text to label clearly what each text space is used for.
13. Drag three TextBox components directly below the Customer Name text box.
14. Make TextBox1 active by clicking it in the Components column. Click the Rename button and change the name to txtAddress
. In the Properties column, change the Hint
property to Enter Address
.
15. Select TextBox2 and rename it as txtCityState
. Change the Hint
property to City, State
.
16. Select TextBox3 and rename it as txtZip
. Change the Hint
property to ZIP Code
(or Postal Code
).
17. From the Basic palette, drag a ListPicker component and drop it below the txtZip text box.
A list picker looks like a button on the interface, but when it’s tapped, it allows you select an item from a predefined list. Although you can define the items in the list picker with the Elements from String
property in the Properties column, for this project, define the list of items to be picked from within the Blocks Editor.
18. Rename the ListPicker1 component to lstpItems
. You will use the lstp
prefix to denote a list picker through this book. When the list picker is clicked by your user, you set the text on the button to indicate the item they have chosen. However, the button for the ListPicker starts with some text to prompt the user to select an item. Change the Text
property in the Property column to Select an Item
.
19. Drag two CheckBox components from the Basic palette and drop them under the item list picker.
Check boxes are a two-state reporter. A check box is always one of two states: true or false. A state of true means that the check box is currently checked. False means that the check box is not checked. You can use the “true or false” nature of the check box to report on your form whether it is true that the customer has paid in full or will pay cash on delivery.
20. Make the CheckBox1 component active by clicking on it in either the Viewer or the Components column. Rename CheckBox1 to chkPaidFull
. In the Properties column, change the Text
property to Paid in full
. Change the TextColor
property to white
by using the color picker.
I use the chk prefix to denote a check box throughout this book.
21. Make the CheckBox2 component active by clicking it in either the Viewer or the Components column. Rename CheckBox2 as chkCOD
. In the Properties column, change the Text
property to COD
. Change the TextColor
property to white
by using the color picker.
22. Drag and drop a button component below the COD check box. Change the name to btnSendEmail
in the Components column. In the Properties column, change the Text
property to Submit Order
.
The Submit Order button is the last thing the user taps to send the completed form to a predetermined address.
23. Open the Other Stuff palette in the Palette column. Drag and drop a Notifier component onto the Viewer workspace.
The Notifier component gives you the ability to have several different types of notifications:
• ShowAlert: Displays a simple text pop-up at the bottom of the device screen
• ShowChooseDialog: Puts up a pop-up text box with a message, title, and two buttons
• ShowMessageDialog: Displays a pop-up text box with a single button
• ShowTextDialog: Gives you a pop-up message with a text box for the user to enter text
You use the third option, ShowMessageDialog, after a check to make sure that a customer name has been entered in the form fails. The notifier alerts the user to an empty text box.
All of the properties and settings for the Notifier component are set using blocks logic in the Blocks Editor.
Adding New Components to OrderDroid 1.0
The next steps guide you through adding the e-mail functionality. If you have your own application that you want to add e-mail to, this is where you should start. You use the typeblock method of creating most of your blocks in this section. Typeblocking is a good way to speed up development. Simply start typing the name of the block you want and a list of possible blocks appears on the Blocks Editor workspace. When you see the block you want, press Enter and the block is created on the workspace. This is a significant speed-up from opening each component or block drawer and dragging out the desired blocks.
Along with typeblocking, you can use the Tab key to change the active selected block. A combination of typeblocking, using the Tab key, and copying/pasting with keyboard shortcuts allows you, in time, to program in App Inventor without a lot of mouse movement.
However, whenever you see typeblock in a step, you can always open the required block or component drawer and drag out the component.
1. Drag and drop an ActivityStarter component from the Other Stuff palette onto the Design view.
2. In the Properties column, set the Action
property field (the Action
field is the first property field in the Properties column) value to android.intent.action.VIEW
.
The ActivityStarter component allows your application to start other applications on your phone while handing them data to process. For the OrderDroid application, you use ActivityStarter to send a standard mailto link to the built-in Android browser. The browser in turn starts the default e-mail handling application. The properties of the ActivityStarter are complex and arcane. They are the closest to the underlying code that makes up the instructions to your Android phone. Because of the relatively low-level nature of the ActivityStarter, it is fairly sensitive to any errors in its usage. The ActivityStarter usually responds to being used incorrectly by ungracefully forcing your application to close. If your project is causing force close errors and it has an ActivityStarter in it, you should suspect the ActivityStarter first and foremost.
No ActivityStarter actions work while the phone is connected to the App Inventor: In other words, when your project is running in Development mode and connected via USB. Any attempt to use the ActivityStarter functions while connected and running your project via App Inventor results in the project crashing on your phone. ActivityStarter applications must be packaged and installed on the phone before they can be tested. That includes your OrderDroid application, so don’t try to send the e-mail while the phone is connected to a computer.
At this point, the visual user interface components should be in place. The Design view should look like Figure 4-2. Your connected Android phone will look considerably different — like Figure 4-3.
Figure 4-2: The Customer Information form takes shape
3. Switch to the Blocks Editor. If it is not open, click the Open Blocks Editor button on the Design view.
When you need to do something before anything else happens in your application, use the Screen1.Initialize
block. The Screen1.Initialize
is a special event handler. The event that it handles is the startup of your application. Anything that needs to occur when your application starts should be placed in the Screen1.Initilize
block.
You have a list picker in your application that needs a list of items populated as selection options. The ListPicker component gives you the block set lstpItems.Elements
to
block, but you need an event to execute the block.
Figure 4-3: The phone view of the OrderDroid user interface
4. Open the Screen1 blocks drawer by clicking the Screen1 text on the My Blocks tab. Locate and drag the Screen1.Initilize
block onto the workspace.
5. Open the lstpItems blocks drawer, locate the set lstpItems.Elements
to
block, and snap it into the Screen1.Initialize
event handler.
Now you need to make a list of items in that set lstpItems.Elements to
socket.
6. Open the Lists blocks drawer on the Built-In tab of the Blocks Editor.
List blocks allow you to manipulate arrays of data in App Inventor. For now, you are only concerned with the first block in the drawer. Drag a Make a List
block and socket it into the set lstpItems.Elements to
socket. Each time you place something into a socket on the Make a List
block, it expands and places a new item
socket.
7. Click any blank spot on your Blocks Editor workspace. Type the word text
and press Enter.
App Inventor creates a text
block and highlights the default text, making it ready for you to replace default text with whatever you like. This is called typeblocking and you saw it in action in Chapter 3 when you typeblocked the number 1000. Throughout this book, I show you how to use typeblocking to save yourself time and to aid in learning efficiency. Any time a project refers to typeblocking, start typing the name of the block. If similarly named blocks exist, a drop-down list of possible blocks appears. You can use the arrow keys on your keyboard to highlight the desired block; then press Enter. You can also use the mouse to click the desired block’s name in the drop-down list.
8. Replace the default text in your typeblocked text
block with ‘Andy’ Android Figurine
. Drag the text
block into the Make a List
block and socket it in the item
socket. The block expands and adds a new socket.
9. Typeblock a new text
block by clicking in the empty workspace, typing the word text
, and pressing Enter.
Remember you can also drag a text
block from the Text blocks drawers on the Built-In tab. Typeblocking is just a little faster and more efficient.
10. Replace the default text in your new text
block with Android Laptop Decal
. Socket your new text
block into the open socket on the Make a List
block (see Figure 4-4).
Figure 4-4: The ListPicker Elements set with Make a List
11. Typeblock one more text
block and set its text to App Inventor Desktop Blocks Set
. Socket that text into the Make a List
block as well.
12. You can test your list picker now on your phone. Tap the Select Item button on the connected Android phone to see the list of items pop up. Selecting one of the items has no effect yet. Close the list picker to return to the application.
When one of the items is picked from your ListPicker, you need to keep it stored until it is sent in an e-mail. Remember that storing information temporarily in App Inventor means that you use a variable. Because you foresee adding multiple items to the order form in future versions, you are going to define a storage container for all the items that will be purchased. You will define a variable to be the shopping cart for the order form.
13. Typeblock a new variable by clicking on a blank spot on the workspace, typing vari
, and then pressing Enter. A list of possibilities appears in a drop-down list. As you type, App Inventor filters through all of your defined components and blocks. When the component or block you wish to typeblock is at the top of the drop-down list, you can press Enter and that block is created (see Figure 4-5). The newly created variable block has its default text of variable
highlighted and ready for you to change. Rename the variable varShoppingCart
. A variable cannot have an empty socket, so you need to typeblock a text
block by typing text
and pressing Enter. Clear the text from the created block and socket it in the new variable.
Figure 4-5: Typeblocking a new variable block
You can open the My Definitions drawer to see the two new blocks created by typeblocking the new variable. The global varShoppingCart
block is for pulling information out of the variable and the set varShoppingCart to
block is for putting information into the variable.
14. Now that you have a place to store the selected item, you need to handle the event of a user picking an item from the list picker. The AfterPicking
event allows you to execute instructions when a user picks something from a list picker.
15. Open the lstpItems drawer on the My Blocks tab and drag and drop the lstpItems.AfterPicking
event from the lstpItems drawer. After your user selects an item from your list picker, the blocks in this event are executed.
16. You store the item picked in your varShoppingCart
variable. Open the My Definitions drawer on the My Blocks tab, drag out the set VarShoppingCart to
block, and socket it into the AfterPicking
event handler. The ListPicker component has a block that reports the results of the user’s selection. You socket that block into the set VarShoppingCart to
block. This sets the contents of your variable to the item that the user selected.
17. Open the lstpItems drawer and locate the lstpItems.Selection
block. Drag the lstpItems.Selection
block and socket it into the set varShoppingCart to
block.
To test your blocks up to this point, you need to know about watching your blocks. Watching is the primary way you use to debug and learn about your applications in Google App Inventor. Right-click the def varShoppingCart block and select the Watch option from the menu that appears. An empty Watch “balloon” pops up. This balloon populates in real time with whatever that variable currently holds, as shown in Figure 4-6. On your connected Android phone, tap the Select Item button and select one of the items that appears. The Watch balloon in the Blocks Editor populates with your selection. If the Watch balloon seems to disappear, click the Watch square on the watched block to stick it open.
Figure 4-6: Watch balloons are invaluable in troubleshooting your application projects
18. You want the ListPicker button to reflect the user’s selection. When a user selects App Inventor Desktop Blocks Set
, you want the button that once said Select an Item
to reflect the user’s choice. You can change the text property of the ListPicker button by using the set lstpItems.Text to
block.
19. Open the lstpItems drawer and locate the set lstpItems.Text to
block. Drag and drop it under the set varShoppingCart to
block in the AfterPicking event handler. Open the lstpItems drawer and locate the lstpItems.Selection
block again. Drag and socket the lstpItems.Selection
into the set lstpItems.Text to
block (see Figure 4-7).
You used the lstpItems.Selection
block previously to store the list picker selection into our shopping cart variable. This time it is pumping the same information, the user’s selected item, into the text of the ListPicker button.
Figure 4-7: The ListPicker and ShoppingCart blocks
Gathering your form data to be e-mailed
Now you need to gather up all of the form data and e-mail it to a preset order processing address. Keep in mind that in the future, this process for e-mailing the order form needs to accommodate multiple items and variable addresses:
1. You named your submit order button btnSendEmail, so open its drawer on the My Blocks tab and drag out the event handler for btnSendEmail.Click
. Drop it on to the workspace.
You will place the blocks to execute when the user thinks the order is ready to send. An easy way to identify event handlers is the when
keyword they are all labeled with. An event handler always says “when something happens, do something.”
Many times, you need to include logic to make sure that data a user has entered fits your requirements (for example, a ZIP code must be a number instead of a text string). You may also want to verify that certain fields have data. In traditional programming terminology, this kind of logic is called validation. It validates user input and sometimes sanitizes it so that it can be used. In App Inventor, these kinds of checks utilize the built-in control blocks.
You build logic into the button click
event to make sure that the name and the address field have content before you allow the e-mail to be sent. Your algorithm requires the kind of logic that says, “If the address field is empty, don’t send the e-mails; otherwise, go ahead and send the e-mail.” You use the IfElse
block to accomplish this validation task. In this case, you use a nested IfElse
. You place one IfElse
block in the socket of another IfElse
block. You can do this to ask multiple questions about data test or conditions. You check first for the Name field for content and, if that passes, you check the Address field.
2. Open the Control blocks drawer on the Built-In tab of the Blocks Editor and drag an IfElse
block into the btnSendEmail.Click
event handler.
Now you build the test condition. If the Name field is empty, you use the Notifier component to warn the user. If it’s not empty, you proceed to checking the Address field.
3. Typeblock a comparison operator by typing an =
and pressing Enter. Socket that comparison operator into the test socket on the IfElse
block. You want to compare the contents of the Customer Name text field with a blank text
block.
4. Open the txtCustomerName drawer and locate the txtCustomerName.Text
block. This block reports the contents of the text box. Drag the txtCustomerName.Txt
block and socket it into the first socket on the comparison operator (see Figure 4-8).
5. Typeblock a text
block by typing text
and pressing Enter. Delete its default value, leaving an empty text
block. Snap the empty text
block into the second socket on the comparison operator.
This test condition tests whether the Customer Name text box is equal to “ “ or nothing. If the user has neglected to populate the customer name field, the condition evaluates as True
and execute the blocks in the then-do
of the IfElse
block.
You use the Notifier component to clearly indicate to the user the lack of data in the form.
6. Open the Notifier1 blocks drawer on the My Blocks tab. Locate the Notifier1.ShowMessageDialog
block. Drag the Notifier1.ShowMessageDialog
block and snap it into the then-do
socket on the IfElse
block (see Figure 4-8).
The ShowMessageDialog
has three sockets that require text. They are a little out of logical order:
• The first, message
, is the text that is displayed in the dialog pop-up box. Typeblock a text
block by typing text
and pressing Enter. Replace the default text with Please enter a Customer Name…
and press Enter. Snap the text
block into the message
socket on the Notifier1.ShowMessageDialog
block.
• The second socket on the ShowMessageDialog
block, title
, will be the text at the top of the dialog box pop-up. Typeblock a text
block. Replace the default text in the text
block with Attention
and press Enter. Drag the text
block into the title
socket on the ShowMessageDialog
block.
• The third socket on the ShowMessageDialog
block is button text
. This is the text on the button to dismiss the notification. Typeblock a new text
block and change the default text to OK
. Drag the text
block and socket it into the buttonText
socket on the Notifier1.ShowMessageDialog
block.
The btnSendEmail.Click
event handler should now look like Figure 4-8.
7. Test your application behavior by tapping the Submit Order button on your connected Android phone, with no text in the Customer Name field. You should get the notification pop-up.
If the Customer Name field is populated, you want to move on and perform the exact same evaluation on the address field.
Figure 4-8: The completed notification block
8. Drag another IfElse
block from the Control blocks drawer on the Built-In tab and socket it in the else-do
of your first IfElse
block. This creates nested IfElse
blocks. Typeblock a comparison operator by typing an =
(equals sign) and pressing Enter. Socket the comparison operator into the test
socket of your nested IfElse
block.
9. Open the txtAddress blocks drawer by clicking it on the My Blocks tab. Locate the txtAddress.Text
block. This block reports the contents of the text box. Drag the txtAddress.Text
block and socket it into the first socket on the comparison operator in your nested IfElse
block.
10. Typeblock a text
block and delete the default text to leave an empty text
block. Drag the empty text
block into the second socket in your comparison operator.
If this test evaluates as true
, it means that the user neglected to put any information in the address field, so you need to notify them of this. The address field is important enough that you want to get the address from the user immediately. Having an order with no deliverable address is a disaster. For this task, you use a different Notifier
block. The ShowTextDialog
prompts the user to enter the address before it is dismissed.
11. Open the Notifier1 blocks drawer by clicking it on the My Blocks tab. Locate the Notifier1.ShowTextDialog
block and drag it into the then-do
socket in your nested IfElse
block (see Figure 4-9).
You have taken care of the first notification with the previous steps. Now you need to provide the text for the second notification.
12. Typeblock a text
block and change the default text to Please enter a customer address
. Snap the text
block into the message
socket on the Notifier1.ShowMessageDialog
block.
13. Typeblock another text
block and change the default text to Attention
. Drag the text
block into the title
socket on the Notifier1 block.
14. The ShowTextDialog
block generates a pop-up dialog box, as shown in Figure 4-10. There is a text box for the user to enter text. When the OK button is tapped, an event is generated and the text from the dialog box can be handled any way you like.
Figure 4-9: The Notifier1.ShowTextDialog block
Figure 4-10: The ShowTextDialog notification and text box
15. To control and take advantage of this text box in the dialog box, open the Notifier1 blocks drawer and locate the Notifier1.AfterTextInput
event handler. Drag the event handler onto the Blocks Editor workspace (see Figure 4-11).
Figure 4-11: The AfterTextInput event handler
16. After a user inputs the address in the dialog box, you want to populate the Customer Address field on your main form with the entered text. Open the My Definitions blocks drawer.
You will see a new block that was created when you dragged out the Notifier1.AfterTextInput
event handler. The value response
block contains the text the user inputs in the text box.
17. Open the txtAddress blocks drawer and locate the set txtAddress.Text to
block. Drag and drop it into the Notifier1.AfterTextInput
event handler.
18. Open your My Definitions drawer and drag the value response
block and socket it into the set txtAddress.Text
to
block (see Figure 4-12).
19. Test your application behavior on your connected Android phone. Populate the Customer Name text box with some text but leave the Address text box empty. Tap the Submit Order button. When the dialog box pops up, enter some text into the dialog text box and tap OK.
You should see the text you entered in the dialog text box appear in the Address text box.
At this point in your project, you have accomplished the following goals:
• Created the form for gathering customer data
• Created a list picker with items for selection
• Created validation checks for critical fields in the form
Your btnSendEmail.Click
event handler should look like Figure 4-12. The only socket left empty is the final else-do
in your nested IfElse
block. In the next section, I show you how to create a procedure to handle the e-mail creation and sending and then call the procedure in this else-do
socket.
Figure 4-12: The validation checks in the btnSendEmail.Click event handler
Creating an e-mail
The ActivityStarter uses its DataURI
property to pass a mailto link to the Android built-in link handler. You will define a procedure to handle the gathering and building of the e-mail text and the actual sending of the e-mail. You use a standard mailto link to send your e-mail. The e-mail mailto syntax is fairly simple, but it requires a strict adherence to a preset format. Mailto links are those links on Web pages that launch your e-mail client and automatically populate an e-mail message with address and subject information. The format is as follows:
mailto:[email protected]?subject=Subject text&body=body text%0AA new line.%0AThirdline
The important parts to remember are
• The mailto:
, which is needed to tell the built in browser to call the default client
• The single ?
after the e-mail address
• The subject and body keywords used to prepopulate the e-mail in the default client
• The ampersand (&
) between the keywords
• The %0A
, which indicates a new line for the e-mail body text
You use text function blocks to build up the mailto link and then use the ActivityStarter to call the default link handler on the Android device. Remember that the ActivityStarter cannot be tested while in development mode (that is, while it's connected to App Inventor). It will crash the application. To test this part of your application, you need to package and install your application. Refer to Chapter 1 for a refresher on how to package and install your applications. Here's how to get started creating the e-mail:
1. Open the Definitions blocks drawer on the Built-In tab. Drag a Procedure
block onto the Blocks Editor workspace. Rename the Procedure procSendMail
.
Make sure you do not grab a Procedure with Result
block by mistake. I show you how to work with the Procedure with Result in Chapter 10.
The first thing you have to do is set the DataURI
property of the ActivityStarter with the complete mailto link. The mailto link contains all of the text for the e-mail address, and the subject and body of the e-mail.
2. Open the ActivitStarter1 blocks drawer on the My Blocks tab. Locate the set ActivityStarter1.DataUri to
block and drag and socket it into the procSendMail
procedure.
3. Open the Text blocks drawer on the Built-In tab. Drag a make text
block on the Blocks Editor workspace.
The make text
block is an expanding block. Every time you socket something into its text
socket, it creates another text
socket. You can build a text up from various elements such as variables, text boxes, and text blocks. It reports the result of all of its text
sockets in a single text string. You build up the mailto string in such a way that it can be easily maintained and expanded in a later version upgrade point.
4. Typeblock a text box by typing text
and pressing Enter. You will be using several text
blocks, so select the newly created text
block and copy it into memory by pressing Ctrl+C on your keyboard. Press Ctrl+V to paste the text
block onto the workspace whenever you need a new text
block.
5. Change the default text of your first text
block to mailto:
without the quotes. Snap the mailto
block into the text
socket on the make text
block. A new text
socket will be created.
6. Use Ctrl+V to create a new text
block. Change the text to the e-mail address you want to send the completed form to. You might want to use your own e-mail address so you can see the result when you test the completed application. Snap the e-mail text
block into the new text
socket on the make text
block.
In a future version, you might want to replace this block with an address from the contacts or from a text field that you allow the user to input.
7. Use Ctrl+V to create a new text
block. Replace the default text with ?subject=A new order from OrderDroid
. Snap the Subject block into the next text
socket on the make text
block.
8. Use Ctrl+V to create a new text
block. Replace the default text with &body=
. Snap the Body block into the next text
socket on the make text
block. You will separate the body=
tag from the actual body text so that it can be changed later with variables or information from future versions of the OrderDroid application.
9. To prepare for creating the body of the e-mail, drag all the necessary blocks and place them on the workspace for when you need them. You create a nicely formatted e-mail from all of the text entered into the text boxes on your form. So, you will need the .Text
blocks from all of your text boxes and the .Value
blocks from your check boxes (see Figure 4-13).
10. Open the txtCustomerName drawer on the My Blocks tab and drag out the txtCustomerName.Text
block.
Open the txtAddress drawer and drag out the txtAddress.Text
block.
11. Open the txtCityState drawer and drag out the txtCityState.Text
block.
Open the txtZip drawer and drag out the txtZip.Text
block.
12. Open the chkCOD drawer and drag out the chkCOD.Value
block.
Open the chkPaidFull drawer and drag out the chkPaidFull.Value
block.
13. Open My Definitions drawer and drag out the global varShoppingCart
variable block.
Figure 4-13: Preparing to build the body of the mailto link
If you get lost or confused while building this long make text
block, just flip ahead to Figure 4-14.
14. Typeblock a new text
block and change the default text to Customer Name:%0A
. Remember that the %0A
creates a new line, so you are creating the text Customer Name:
and then a new line. Drag the text
block with Customer Name:%0A
and plug it into the text
socket on the make text
block.
15. Snap the txtCostumerName.Text
block you placed on the workspace earlier into the next text
socket.
Typeblock a text
block and replace the default text with %0A
. Place the newline block in the next text
socket.
16. Typeblock a new text
block and change the default text to Customer Address:%0A
. Snap the Customer Address%0A
block into the next text
socket on the make text
block.
Snap the txtAddress.Text
block into the next text
socket on the make text
block.
17. Typeblock a text
block and replace the default text with %0A
. Place the newline block in the next text
socket.
18. Snap the txtCityState.Text
block into the next text
socket.
Typeblock a text
block and replace the default text with %0A
without the quotes. Place the newline block in the next text
socket.
19. Snap the txtZip.Text
block in the next text
socket.
Typeblock a text
block and replace the default text with %0A
. Place the newline block in the next text
socket.
20. Typeblock a text
block and replace the default text with Purchased Items:%0A
. Drag the Purchased Items
block and socket it in the next text
socket.
21. Snap the global varShoppingCart
block into the next text
socket.
Typeblock a text
block and replace the default text with %0A
. Place the newline block in the next text
socket.
22. Typeblock a text
block and replace the default text with Payment Type:%0A
. Snap the Payment Type
block into the next text
socket.
23. Typeblock a text
block and replace the default text with COD=
. Drag this text
block into the next text
socket.
Snap the chkCOD.Value
block into the next text
socket.
24. Typeblock a text
block and replace the default text with %0A
. Place the newline block in the next text
socket.
Typeblock a text
block and replace the default text with Paid in Full=
. Place this block in the next text
socket.
25. Snap the chkPaidFull.Value
block in the next text
socket.
Typeblock a text
block and replace the default text with %0A
without the quotes. Place the newline block in the next text
socket.
26. Finally, drag the entire make text
block and socket into the ActivityStarter1.DataUri
block in your procSendMail
procedure (see Figure 4-14).
Figure 4-14: The completed procSendMail with make text block for the mailto link
Because you set the Action
property in the Properties column of the Design view, all that is left for you to do is to call the ActivityStarter in your procSendMail
procedure:
1. Open the ActivityStarter1 drawer and drag and drop the call ActivityStarter.StartActivity
block below the ActivityStarter1.DataUri
block in the procSendMail
procedure block. (Refer back to Figure 4-14.)
2. Open the My Definitions drawer on the My Blocks tab. Drag the call procSendMail
block and socket it into the final else-do
in the btnSendEmail
event handler. See Figure 4-15.
Figure 4-15: The completed btnSendEmail event handler.
The completed OrderDroid 1.0 blocks are shown in Figures 4-14 and 4-15.
3. Click back over to your Design view to package and install the application to your phone for testing. If you get a force close error, make sure that the ActivityStarter Action
property is correctly set.
Creating OrderDroid 2.0
OrderDroid 2.0 progresses from the 1.0 version to include new functionality and bring OrderDroid to the high level you want for an app you’re going to deploy. Building the previous version with maintainability in mind makes the expansion of the OrderDroid project smoother and allows for future expansion as well.
Your design
The 2.0 version of OrderDroid changes both the look and the functionality of the application. With OrderDroid 2.0, you learn how to create and use multiple VirtualScreens. Multiple VirtualScreens allow you to include more components and organize your applications logically. Although the second version of this project will not include a whole bunch of new blocks or components, you learn more about creating logic flow and algorithm logic to solve seemingly complex problems. The challenge of keeping all the product items in the shopping cart and formatting them once for display and again for e-mailing takes up most of your time in version 2.0.
Figure 4-16: Design sketches for VirtualScreens 1 and 2 for OrderDroid 2.0
These are your design goals for moving the OrderDroid app to the next milestone:
1. Add a screen for multiple items to be added to the shopping cart.
2. Add the ability to set the address to send e-mail.
3. Include a variable address for order processing.
4. Add the ability to view or clear shopping cart.
Your primitives
These are the primitive programming steps required to achieve your goals:
• A field to enter e-mail addresses to send the order form to
• A new VerticalArrangement to be used as VirtualScreen2
• Navigation buttons to move between VirtualScreens
• A way to keep multiple items in the varShoppingCart
variable
• A way to format and display the shopping cart
• Organizational elements to make the layout usable and attractive
• A way to format the shopping cart for the mailto link
Your progression
This is the basic order for accomplishing your design goals and primitives:
1. Create a second VirtualScreen.
2. Create an e-mail field.
3. Create navigation buttons.
4. Create the shopping cart display.
5. Create the shopping cart Clear button.
6. Create the navigation logic.
7. Create the shopping cart logic.
8. Change the e-mail procedure.
New components
The new concept of VirtualScreens is important for future applications:
• VirtualScreens
New blocks
These are the new blocks used for building version 2.0:
• ForEach
• Add Item to List
You will be expanding the previous version of the OrderDroid application, but you do not want to lose the current version, so you should save a copy and work on the copy:
1. Open the OrderDroid1_0 project.
2. Select the Save As button in Design view above the Viewer.
The default Save As name is OrderDroid1_0copy.
3. Change the Save As name to OrderDroid2_0.
A copy of the 1.0 version is made and renamed OrderDroid2_0. You will be editing the newly named OrderDroid2_0 copy.
The first VerticalArrangement that you placed in the OrderDroid 1.0 project was renamed to VirtualScreen1 in preparation for a version with more virtual screens. You use another VerticalArrangement to act as a holder for all of the elements meant to show up for VirtualScreen2.
App Inventor does not currently support multiple screens in the traditional sense of the idea. However, you simulate the exact same effect using virtual screens. VirtualScreen1 starts with the Visible
property set to true
. VirtualScreen2 starts with its Visible
property set to false
. The result is that all the components in VirtualScreen1 are visible and all the components in VirtualScreen2 are invisible. You can harness this behavior by having a button event that changes the two states so that the invisible becomes visible and vice versa. If you get lost or confused while setting up the user interface for OrderDroid 2.0, flip forward to Figure 4-17 for clarification.
Getting Started on OrderDroid 2.0
The VirtualScreens are VerticalArrangements that you repurpose as containers for all the required elements for a given user interface screen. Pay close attention to the following steps so you can reproduce them for your own applications:
1. To begin, drag and drop a VerticalArrangement from the Screen Arrangement palette below the existing VirtualScreen1. Rename this VerticalArrangement as VirtualScreen2
.
2. In the Properties column, uncheck the Visible
property. Because you will be using the component centering method you used in the SounDroid project, make sure the Width
and the Height
property on both VirtualScreens is set to Fill Parent
.
The second virtual screen is the Shopping Cart screen. From this screen, the user can select items to add to the cart. The ListPicker component named lstpItems needs to be moved to the second virtual screen.
3. Click on the ListPicker component in the Viewer and drag it down into VirtualScreen2.
Most of the screen space on VirtualScreen2 is taken up with item listings for the shopping cart. You need a label to indicate what you are displaying.
4. From the Basic palette, drag a label below the ListPicker in VirtualScreen2. In the Components column, rename the label lblShoppingCartLabel
. Set the TextColor
property to white
and then change the default text to Shopping Cart Contents:
.
Drag a second label from the Basic palette and drop it below the lblShoppingCartLabel
. In the Components column, rename the label to lblShoppingCartDisplay
. In the Properties column, change the TextColor
property to white
. Delete the default text, leaving an empty label. Set the Width
and Height
property to Fill Parent
. Refer to Figure 4-17 for layout reference.
Adding navigational elements
After you have your shopping cart display set up, you need to put in place the navigation elements that allow users to move back and forth between the virtual screens by toggling the visibility of the VirtualScreen components:
1. Drag a HorizontalArrangement from the Screen Arrangement palette and drop it directly below the Shopping Cart display label. Set its Width
property to Fill Parent
.
This acts as a container for two buttons: one to navigate back to the Order form and the other to clear the contents of the shopping cart.
2. Drag a button from the Basic palette into the HorizontalArrangement you just placed. This is the button to go back to the main order form screen. Change the name to btnBackToForm
. Change the default text to Back to Order Form
.
Next you use an empty label as padding between the Back button and the Clear Shopping Cart button.
3. Drag a label next to the Back button. In the Components column, rename the label padButtonSpace2
. Delete the default text and leave the label blank. Set the Width
property to Fill Parent
.
The label keeps the buttons equally spaced at the bottom of the Virtual Screen.
4. Drag and drop another button next to the padding label. In the Components column, rename the button btnClearCart
. Change the default text to Clear Shopping Cart
.
Your VirtualScreen2 is complete. Now you need to add a navigation button on VirtualScreen1 to enable VirtualScreen2. You need a HorizontalArrangement to keep the Submit button and the navigation button arranged nicely.
5. Drag a new HorizontalArrangement below the Submit Order button. In the Properties column, set the Width
property of the HorizontalArrangement to Fill Parent
.
6. Drag and drop the Submit Order button into the HorizontalArrangement.
You will use a padding label as in Virtual Screen2 to separate the two buttons. Drag a label from the Basic palette and drop it into the HorizontalArrangement. Rename the Label padButtonSpace1
. Delete the default text leaving an empty label. Set the Width
property to Fill Parent
.
7. Drag a new button to the right of the padding label in the HorizontalArrangement. Rename the button btnToCart
. Change the default text to Open Shopping Cart
.
On your connected Android device, you will notice that there is space below the Submit and Navigation buttons. To keep VirtualScreen1 and VirtualScreen2 consistent and looking nice, put a HorizontalArrangement above them and set it to Fill Parent
. The HorizontalArrangement also holds the text box for the user to enter an e-mail address to send the order form to:
1. Drag and drop a new HorizontalArrangement between the COD check box and the HorizontalArrangement holding the buttons. In the Properties column, set both the Width
and Height
property of the arrangement to Fill Parent
.
2. Drag and drop a label into the new HorizontalArrangement. In the Components column, rename the label lblEmailAddressLabel
. Change the default text to Receiving Email:
. Change the default text color to white
.
3. Drag and drop a text box from the Basic palette to the lblEmailAddressLabel
. Change the name of the text box to txtEmailAddress
. Change the default Hint text to Enter Email Address
. This will be the text box in which your user enters the e-mail address for the mailto link.
At this point, your component layout should look like Figure 4-17.
Figure 4-17: Both VirtualScreens of the OrderDroid 2.0 user interface
Make sure your Blocks Editor workspace is scrolled to a clean workspace area away from the programming blocks that give your OrderForm its current functionality. Hover your mouse over the mini-map in the upper right of the Blocks Editor and click on an empty space to move your current workspace to that spot.
Switch over to the Blocks Editor. Your first task is to set up the logic for the two navigation buttons that allow the user to move between VirtualScreen1 and VirtualScreen2. Use the .Click
event handlers for the btnToCart
and the btnBackToForm
to toggle the visibility property on the VirtualScreens.
1. Open the btnToCart blocks drawer by clicking it on the My Blocks tab. Drag the when btnToCart.Click do
event handler out onto the workspace.
2. Open the btnBackToForm blocks drawer and drag the when btnBacktoForm.Click do
event handler to the workspace.
3. Open the VirtualScreen1 blocks drawer and drag out the set VirtualScreen1.Visible to
block. Select the block so that it is highlighted and press Ctrl+C to copy the block into memory. Then press Ctrl+V to paste a copy of the block. You should now have two set VirtualScreen1.Visible to
blocks.
4. Open the VirtualScreen2 blocks drawer and drag out the set VirtualScreen2.Visible to
block. Copy and paste the block so that you have two set VirtualScreen2.Visible to
blocks.
5. Drag one of the set VirtualScreen1.Visible to
blocks into the btnToCart.Click
event handler, and then drag one of the set VirtualScreen2.Visible to
blocks into the btnToCart
.Click event handler (see Figure 4-18).
6. Drag the two leftover VirtualScreen.Visible
blocks into the btnBackToForm.Click
event handler.
You now need to provide a value for the .Visible
blocks. The btnToCart.Click
handler is for the To Shopping Cart button. Tapping it should make VirtualScreen1 invisible and VirtualScreen2 visible.
1. Typeblock a false
block by clicking on a blank area of the workspace, typing false
on your keyboard, and pressing Enter. Snap the false
block into the set
VirtualScreen1.Visible to
in the btnBackToForm.Click
block.
2. Type block a true
block by typing true
and pressing Enter on your keyboard. Snap the true
block into the socket on the set VirtualScreen2.Visible to
block in the btnToCart.Click
event handler block.
The btnBackToForm.Click
event handler is for the Back to Order Form button on VirtualScreen2. Tapping it should do the exact opposite of the previous event handler.
3. Typeblock a true
block and socket it into the set VirtualScreen1.Visible to
block in the btnBackToForm.Click
event handler.
4. Typeblock a false
block and socket it into the set VirtualScreen2.Visible to
block in the btnBackToForm.Click
event Handler (see Figure 4-18).
Figure 4-18: The completed Navigation button event handlers for the VirtualScreens
Test the navigation buttons on your connected Android device. The buttons should now move you back and forward between the two virtual screens. Voilà! Your application now gives the impression of having two distinct areas of user interface elements. You can use this method to create a wide variety of application functionality.
Storing multiple items and formatting them for display
The design goal of storing multiple items and formatting them for display is the most challenging goal in this project. In the version 1.0 of the OrderDroid project, you just dropped whatever the ListPicker selected into a variable and then e-mailed the contents of the variable. The algorithm for the process looked something like Figure 4-19.
Figure 4-19: The previous shopping cart algorithm
For storing multiple items and then displaying them, you need a more complex process. You will make use of a variable as a list, a temporary formatting variable, and a ForEach
block to create the logic in Figure 4-20.
Figure 4-20: Algorithm for the shopping cart in OrderDroid 2.0
When an item is selected from the ListPicker, it is written to a variable as an item in a list. In App Inventor, a list is a variable that has been defined as a list by using blocks from the List drawer. The varShoppingCart
doesn’t change unless the shopping cart is cleared or an item is added with the ListPicker. The varShoppingCart
list can be used by either the Shopping Cart Display routine or the Email routine to format and then use the formatted text in the formatted shopping cart variable. Another way to think of it is that the varFormattedShoppingCart
is a piece of scrap paper that the two routines use to organize the list text the way they need it. The Display routine needs each list item to be on a new line, so it will use the “
” newline character to format the text. The Email routine needs each list item on a new line as well but must use the %0A
e-mail@@ndspecific newline character.
So breaking that logic down piece by piece, you let the ListPicker.AfterPicking
event handle the updating of the varShoppingCart
variable list. You build a new procedure for the display update, and then you update the existing e-mail procedure to utilize the new shopping cart as a list.
1. In the Blocks Editor workspace, locate the def varShoppingCart
block. It currently has a null or empty text
block in it. Delete the text
block.
You can delete blocks by dragging them to the trash can icon in the lower right corner of the screen or by highlighting them and pressing Delete on your keyboard.
2. Open the List blocks drawer on the Built-In tab of the Blocks Editor. Drag out a Make a List
block and socket it into the varShoppingCart
block (see Figure 4-21).
Locate the lstpItems.Afterpicking
block in the Blocks Editor workspace. This is the event that handles what happens after an item is selected from your ListPicker. Currently it sets the value of the varShoppingCart
to the selected Item from the ListPicker. That will not work with multiple items. Each time an item is selected, it overwrites the previous item that was in the variable. Because we turned the varShoppingCart
into a list, we can now add an item to that list each time an item is selected.
3. Remove the lstpItems.Selection
block from the varShoppingCart
block and set it aside — you will reuse it in a moment.
4. Delete the set global varShoppingCart to
block from the lstpItems.Afterpicking
event.
5. Delete the lstpItems.Text
block that is in the lstpItems.Afterpicking
event block.
This was the block that turned the ListPicker text to the text of the selected Item. This time, you are displaying the list of select items in lblShoppingCartDisplay
.
6. Open the Lists blocks drawer by clicking it on the Built-In tab. Drag out an add items to list
block and snap it into the lstpItems.AfterPicking
event handler (see Figure 4-21).
The Add Items to List
block has two sockets: one for the list you want to add items to, and one for the items to add to the list. Populating the item
socket generates another item
socket on the block.
7. Open the My Definitions drawer on the My Blocks tab. Drag out the global varShoppingCart
block and socket it into the list
socket on the Add Items to List
block. The varShoppingCart
global variable is where your list of items will be stored.
8. Now grab the lstpItems.Selection
block that you set aside earlier (or you can get a new one from the lstpItems blocks drawer) and socket it into the item
socket of the Add Items to List
block (see Figure 4-21).
You will also call the Shopping Cart display procedure in the lstpItems.AfterPicking
event handler, but you haven’t built it yet.
Figure 4-21: The rebuilt blocks without the display procedure
Building the display procedure for the varShoppingCart list
Next, build the display procedure to utilize the items stored in the varShoppingCart
list:
1. Open the Definition blocks drawer from the Built-In tab. Drag a procedure
block onto the Blocks Editor workspace. Click on the procedure
text to rename the procedure. Rename the procedure procUpdateCartDisplay
.
2. Now you need that temporary place to format the list from the varShoppingCart
before displaying it. Open the Definitions blocks drawer on the Built-In tab. Drag out a variable and rename it varFormattedShoppingCart
. Typeblock a text
block by typing the word text
and pressing your Enter key. Socket the empty text
block into the variable you just created.
This is the temporary holding place for the formatted shopping cart before it is displayed or e-mailed.
Because your procedure and the varFormattedShoppingCart
will be used repeatedly, you need to clean the varFormattedShoppingCart
up before repopulating it.
3. Open the My Definitions drawer on the My Blocks tab. Drag out the set
varFormattedShoppingCart
to
block and snap it into the procUpdateCartDisplay
procedure.
4. Typeblock a text
block by typing the word text
and pressing Enter. Delete the default text on the block and snap the empty block into the set varFormattedShoppingCart
block that is now in your procUpdateCartDisplay
procedure.
This clears the variable of any leftover formatted text from previous calls to the procedure.
For every item in the varShoppingCart
variable, we want to display that item, create a new line, display the next item and a new line, and so on. To do this kind of an iterative task, you use a ForEach
block.
5. Open the Control blocks drawer on the Built-In tab. Locate and drag out the ForEach
block. Snap the ForEach
block into the procUpdateCartDisplay
block underneath the set global
block.
The ForEach
block defines its own parameter variable where it places each item from the list while it works on it. You tell the ForEach
block what list you want it to work on in the socket in the lower arm labeled in list
. The ForEach
block then loads each item in the list into the variable defined in its upper arm and does to that item whatever blocks you put between the two arms. When it reaches the last item, your application goes on executing. You can change the name of the parameter variable, but usually you won’t have to.
You need to tell the ForEach
block what list it will be working with.
6. Open the My Definitions drawer, pull out the global varShoppingCart
block, and snap it into the in list
socket in the lower arm of the ForEach
block (see Figure 4-21). Now that the ForEach
block knows what items it will be working with, you need to tell it what to do with each item.
7. You want to take each item and write it to the varFormattedShoppingCart
variable and then write a new line. If you don’t do that, App Inventor lists look like this:
(Item1 Item2 Item3)
Just a bunch of list elements held in parentheses: not very readable at all.
8. Open the My Definitions blocks drawer and drag out the set varFormattedShoppingCart
to block and snap it between the arms of the ForEach
block (see Figure 4-22).
You could just plug in that parameter variable called var
into the variable set block, but that would just write one item from the list to the varFormattedShoppingCart
variable. Each pass of the ForEach
block would write the current contents of the parameter variable over the contents of the varFormattedShoppingCart
. You need to take all of what is in the formatted shopping cart variable and add to it the current contents of the parameter variable. You want all the previous items and newlines plus each item plus a newline. You will use the join
text
block to join the contents of the formatted shopping cart variable with your parameter variable and a newline character. Another way to think about what you are doing is “layering” the information into the varFormattedShoppingCart
by taking what is in the variable and layering the new item and newline on top of the contents, and then placing it all back in the variable.
9. Open the Text blocks drawer on the Built-In tab and drag out a join
block and snap it into the set
varFormattedShoppingCart
to
block that is in the ForEach
block. You are joining the contents of the formatted shopping cart, so open the My Definitions drawer, pull out the global
varFormattedShoppingCart
block, and snap it into the first open socket on the join
block.
You want to join to that variable contents the current contents of the parameter variable and a newline.
10. Open the Text blocks drawer on the Built-In tab, drag out a make text
block and snap it into the second socket on the join block.
11. Open the My Definitions drawer and pull out the value var
block. The value
block reports the contents of the parameter variable var
. Snap the value
var
block into the socket on the make text
block. A new socket is created.
12. Typeblock a new text
block by typing text
and pressing Enter on your keyboard. Change the default text to
. (Make sure the slash is a back slash.)
Updating the shopping cart display
Now the ForEach
block adds all the items in the varShoppingCart
to the varFormattedShoppingCart
one at a time followed by a newline character. Now you have to update the shopping cart display with your newly formatted content. Because there may already be formatted content on the display, first you need to clear it:
1. Open the lblShoppingCartDisplay blocks drawer. Drag out the set lblShoppingCartDisplay.Text to
block and snap it under the ForEach
block. Copy and paste another set lblShoppingCartDisplay.Text to
block or drag it from its drawer. Place the second block under the first (see Figure 4-22).
2. Typeblock a text
block and delete the default text
. Snap the blank text block into the first lblShoppingCartDisplay.Text block
. This clears any text currently in the display.
3. Open the My Definitions drawer and locate the global
varFormattedShoppingCart
block. Drag it out and snap it into the second lblShoppingCartDisplay.Text
block. This populates the display label with the current contents of the formatted shopping cart.
Your procUpdateCartDisplay
procedure should be completed and look like Figure 4-22.
Figure 4-22: The completed procUpdateCartDisplay procedure
Finishing the shopping cart
The only thing left to do for your shopping cart is to call the procUpdateCartDisplay
procedure in the lstpItems.AfterPicking
event:
1. Open the My Definitions drawer and drag out the call procUpdateCartDisplay
block. Snap it in as the very last block into the lstpItems.AfterPicking
event that is already on your workspace.
If your user makes a mistake or needs to start all over again selecting items, they can click the Clear Shopping Cart button. The Clear Shopping Cart button clears both the shopping cart variable and the shopping cart display.
2. Open the btnClearCart blocks drawer and drag out the when
btnClearCart.Click
do
block.
3. Open the My Definitions blocks drawer and drag out the set varShoppingCart to
block and snap it into the when btnClearCart.Click
do
event handler.
4. Typeblock a Make a List
block and snap the Make a List
block into the set varShoppingCart to
block. When the block is executed, this clears the variable.
When you are clearing a variable used as a list, you must use a Make a List block to clear it. If you clear with a text block, you get an error when you attempt to use it as a list again.
5. Open the lblShoppingCartDisplay
blocks drawer. Drag out the set
lblShoppingCartDisplay.Text to
block and snap it into the btnClearCart.Click
block.
6. Typeblock a text
block and delete the default text. Snap the empty text
block into the set lblShoppingCartDisplay.Text to
block on your keyboard (see Figure 4-23). This clears the Shopping Cart display.
Figure 4-23: The clear button event handler
Test the item selection, display, and shopping cart clearing on your connected Android device. If you experience any trouble, go back carefully over all the figures in the 2.0 version to spot any differences.
The e-mail procedure
The process of formatting the shopping cart for display is almost exactly duplicated in the e-mail procedure, except the newline character will be different. The e-mail procedure formats all of the selected items and the customer information to be so it can be sent with the mailto link and the ActivityStarter. The mailto only recognizes the %0A
as a newline. You use a ForEach
loop to create the items in the varShoppingCart
with the %0A
character. Then you partially dismantle the make text
that makes up the mailto link text. You replace the varShoppingCart
variable with the varFormattedShoppingCart
and replace the e-mail address with the text from the e-mail address text box on VirtualScreen1.
Just as you did in the update display procedure, you should flush out anything that might have been put into the varFormattedShoppingCart
:
1. Locate the procSendMail
block in your Blocks Editor workspace. Open the My Definitions blocks drawer, drag out the set
varFormattedShoppingCart
to
block, and snap it into the procSendMail
above the ActivityStarter1.DataUri
with the long make
text
block in it (see Figure 4-24).
2. Typeblock a text
block and delete the default text. Snap the empty text
block into the set
varFormattedShoppingCart
to
block. This clears anything left over in the variable.
In the next step, be sure to use a new ForEach
block instead of copying the existing ForEach
in the procUpdateCartDisplay
. Just as with all of the other components, the parameter variable’s name must be unique.
3. Open the Control blocks drawer on the Built-In tab, drag a ForEach
block, and snap it below the set
varFormattedShoppingCart
to
block you just placed (see Figure 4-24).
4. Open the My Definitions blocks drawer and drag out the global
varShoppingCart
block. Socket it into the in list
socket on your ForEach
block. Each item in the shopping cart variable is written one by one into the parameter variable var1
for processing.
5. Open the My Definitions drawer and locate the set
varFormattedShoppingCart
to
block. Drag and snap it into your new ForEach
block. You use this variable as a temporary formatting location as you did in the display update procedure.
Join the contents of the formatted shopping cart variable with each item in the varShoppingCart
list variable.
6. Open the Text blocks drawer on the Built-In tab. Drag out a join
block and socket it into the varFormattedShoppingCart
variable in your ForEach block.
7. Open the My Definitions drawer and drag out the global
varFormattedShoppingCart
block. Snap that block into the first open socket on the join
block.
The goal is to add to whatever is in the formatted shopping cart variable the current contents of the var1
parameter variable and a newline character.
8. Open the Text blocks drawer and drag out a make
text
block. Snap the make text
block into the second open socket on the join
block.
Open the My Definitions blocks drawer and locate the value
var1
block. Snap the var1
value block into the make
text
block that is nested in the join
block (see Figure 4-24).
9. Typeblock a new text
block and replace the default text with %0A
. Snap the text
block with the newline character in the open socket on the make
text
block.
Your new blocks in the procSendMail
procedure shown in Figure 4-24 now clear the formatted shopping cart variable, and then iterate through the varShoppingCart
and write each item followed by a newline character into the varFormattedShoppingCart
variable.
Figure 4-24: The new formatting blocks for the procSendMail procedure
You can now use the varFormattedShoppingCart
variable in the make text
block in the procSendMail
procedure that makes the mailto link. Refer to Figure 4-25 to clarify the following directions.
You now alter the long make text
block that is socketed into the ActivityStarter1.DataUri
block. Work from the bottom of the make text
up, removing the following blocks. You remove the text
block with the e-mail address in it and replace it with the text from the txtEmailAddress text box. You also replace the varShoppingCart
block and then replace all of the removed blocks.
Remove all of the blocks in the following list from the make
text
block, working your way up. Set them to the side as you will resocket them in just a minute:
• chkPaidFull.Value
• Paid in Full=
text
• chkCOD.Value
• COD=
text
• Payment type:%0A
text
• The %0A
text
• Remove the varShoppingCart
block and delete it (see Figure 4-25)
• Purchased Items %0A:
text
• %0A
text
• txtZip.Text
• %0A
text
• txtCityState.Text
• txtAddress.Text
• Customer Address:%0A
text
• %0A
text
• txtCustomerName.Text
• Customer Name:%0A
text
• &body=
text
• ?subject=A new order from OrderDroid.
text
• Remove the e-mail address block and delete it
After removing all of the preceding blocks and deleting the varShoppingCart
and [email protected]
text
block, your make text
and all the blocks that were in it should look like Figure 4-25.
Figure 4-25: Rebuilding the make text block for the mailto link
Open the txtEmailAddress blocks drawer on the My Blocks tab. Locate the txtEmailAddress.Text
block. Drag it out and snap it in under the mailto:
text
block in the make
text
block you just cleaned out (see Figure 4-25).
Resocket the following blocks below the txtEmailAddress.Text
block in this order:
• ?subject=A new order from OrderDroid. text
• &body=
text
• Customer Name:%0A
text
• txtCustomerName.Text
• %0A
text
• Customer Address:%0A
text
• txtAddress.Text
• %0A
• txtCityState.Text
• %0A
text
• txtZip.Text
• %0A
text
• Purchased Items %0A:
text
Open the My Definitions drawer and drag out the global varFormattedShoppingCart
block. Snap it into the text
socket (see Figure 4-26).
Continue replacing the following blocks:
• %0A
text
• Payment type%0A
text
• COD
text
• chkCOD.Value
• Paid in Full=
text
• chkPaidFull.Value
Refer to Figure 4-26 to make sure your blocks are in the right order.
Figure 4-26: The rebuilt make text mailto blocks
Congratulations! You have successfully moved the OrderDroid project to its 2.0 version. Go back to the Design view and package the application to your phone. Test it by filling out the form, selecting a few items, and then submitting the order. The order should show up at whatever address you put in the Receiving E-mail Address field.