Explore MIT App Inventor - App Inventor 1 http://dev-explore.appinventor.mit.edu/tutorial-version/app-inventor-1 en Get the Gold http://dev-explore.appinventor.mit.edu/get-gold <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ .ButtonText { color:green; font-weight: bold; } li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } .listblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FCF5D7; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h4 class="ai-header">What You're Building</h4> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGoldMain.png" style="float:right; height: 453px; width: 197px;" /></p> <p> By building the <span style="color:green;">Get The Gold App</span> you will get practice with setting visibility, using Clock components and Timers, and detecting collisions in App Inventor. You'll program an application that has a pirate ship whose goal is to collect all the gold on the screen.</p> <h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name it <span style="color:green;">GetTheGold</span>, and also set the screen's <strong style="color:green;">Title</strong> to "GetTheGold". Open the Blocks Editor and connect to a device or emulator.</p> <h4 class="ai-header">Introduction</h4> <p>This tutorial introduces the following skills, useful for future game development:</p> <ul><li>Using the Clock component</li> <li>Using Clock.Timer to move sprites</li> <li>Using Sprite.Flung to move a sprite </li> <li>Using collision detection</li> </ul><h4 class="ai-header">Getting Ready</h4> <p>For this game, you will have two types of imagesprites: pirate and gold coin. Click below to download the image file for your sprites.</p> <p><a href="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/pirateship.jpeg"><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/pirateship.jpeg" /></a><br /><a href="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/goldcoin.jpeg"><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/goldcoin.jpeg" /></a></p> <h4 class="ai-header">Set up the Components</h4> <p>Use the component designer to create the interface for <span style="color:green;">GetTheGold</span>. When you finish, it should look something like the snapshot below (more detailed instructions below the snapshot).</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGoldDesigner.png" /></p> <p>To create this interface, put the following components into the Designer by dragging them from the Component Palette into the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td><strong>Canvas</strong></td> <td>Basic</td> <td style="color:green;">Canvas1</td> <td>The background that we will be putting our imagesprites on</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">PirateSprite</td> <td>The pirate ship in our game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite2</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite3</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite4</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite5</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite6</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>Clock</strong></td> <td>Basic</td> <td style="color:green;">Clock1</td> <td>We use the Clock for its Timer method to move the coins</td> </tr><tr><td><strong>Button</strong></td> <td>Basic</td> <td style="color:green;">ResetButton</td> <td>To reset the game so the player can play again</td> </tr></table><p>Set the properties of the components as described below:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td><strong>Component</strong></td> <td><strong>Action</strong></td> </tr><tr><td><span style="color:green;">ResetButton</span> </td> <td> Change <span class="ButtonText">Text</span> property to "Reset". </td> <td> </td> </tr><tr><td><span style="color:green;">PirateSprite</span> </td> <td> Change <span class="ButtonText">Speed</span> property to 6. </td> <td> Upload the pirateship image and set <span class="ButtonText">Picture</span> property to pirateship. </td> </tr><tr><td><span style="color:green;">ImageSprite(2,3,4,5,6)</span> </td> <td> Upload the goldcoin image and set <span class="ButtonText">Picture</span> property to goldcoin. </td> <td> </td> </tr><tr><td><span style="color:green;">Clock</span> </td> <td> Change <span class="ButtonText">TimerInterval</span> property to 2000. </td> <td> </td> </tr></table><h4 class="ai-header">Moving the Pirate</h4> <p> To move the PirateSprite, we want the user to be able to "fling" the sprite in the direction that they choose. To do this, we will use the <span class="basicblock">PirateSprite.Flung</span> event handler. </p> <p> You may notice that <span class="basicblock">PirateSprite.Flung</span> takes in 6 attributes: x, y, xvel, yvel, speed, and heading. We want to reassign PirateSprite's current heading to the heading given to us from PirateSprite.Flung. This means that the user can now control the direction of the pirate ship with their fingers by flinging on the screen. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/PirateSpriteFlung.png" /></p> <p>To prevent the pirate from moving off the screen, we will also use PirateSprite.Bounce when an edge is reached. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/PirateSpriteBounce.png" /></p> <h4 class="ai-header">Moving the Coins</h4> <p> We want the coins to move to random positions on the screen. We will use <span class="basicblock">Clock1.Timer </span> and the ImageSprite's MoveTo method to do this. </p> <p> When the Clock1.Timer goes off, we want all of our gold coin ImageSprites to move to a new random location on the Canvas. We will do this by using the <span class="basicblock">Sprite.MoveTo</span> block. </p> <p>MoveTo takes in two arguments: the x and y coordinates on the canvas of the new position we want the sprite to move to. We want the Sprite to move to a new <i>random</i> location so we will use the <span class="basicblock">random integer</span> block found in the Math box. Since we want each Gold ImageSprite to move to a new location, we repeat this process for each sprite's MoveTo function. </p> <p>For ImageSprite2, we want x to be a random integer from 0 to <i>Canvas1.Width-ImageSprite2.Width</i> and y to be a random integer from 0 to <i>Canvas1.Height-ImageSprite2.Height</i>. This is to be repeated for all the Gold Image Sprites.</p> <p>Remember that sprites are measured at the upper left corner as (0,0) so if we don't want them to go off the screen, we need to take the sprite's height/width into account when setting the range for our random numbers.</p> <p>We will do this by setting up our blocks as in the image below:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/ClockTimer.png" /></p> <h4 class="ai-header">Detecting Collisions</h4> <p> App Inventor detects collisions by checking for an intersection between the bounding rectangles of each ImageSprite. We call this rectangle-based collision detection. As you can see in the image below, sprites with circular or polygon shape will appear to collide because of the rectangular bounds around them when they might not actually be colliding.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/CollisionDetection.png" /></p> <p>We can use the <span class="basicblock">PirateSprite.CollidedWith </span> event handler to detect whenever the pirate ship collides with another sprite or gold coin. You may notice that <span class="basicblock">PirateSprite.CollidedWith </span> takes in an argument. This argument is the object that PirateSprite just collided with. We will be testing inside the handler for which object so the name of this argument is not significant. You can name it other. </p> <p>Whenever the pirate collides with a gold coin, we want the coin to disappear. We can do this by setting the coin's visibility to false. To find which coin the pirate collided with, we will use the <span class="basicblock">PirateSprite.CollidingWith</span>. </p> <p> We can use <span class="basicblock">PirateSprite.CollidingWith</span> to take in a component (each of the gold coin sprites) to detect which sprite was hit. This is a component block and NOT a text block with the words ImageSprite inside. The component block can be found in the drawer for each component. If a sprite was hit, we will set its visibility to false. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/CollisionSprites.png" /></p> <h4 class="ai-header">Reset Button</h4> <p>After the user hits all of the gold sprites with the pirate ship, none of them will be visible. The reset button should set all of the gold sprites' visibility to true. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/ResetVis.png" /></p> <h4 class="ai-header">Complete Program</h4> <p>Here's the complete <strong><span style="color:green;">GetTheGold</span></strong> program.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGoldAll.png" /></p> <p>Package the final version of the app by choosing <strong>Package For Phone | Barcode</strong> from the Component Designer menu. When the barcode appears, use the barcode scanner on your phone to download and install the app.</p> <h4 class="ai-header">Variations</h4> <p>Once you get this program running, you may want to do the following additional features to extend it. For example,</p> <ul><li>Create a label to display the time that it took you to get all the gold</li> <li>Change the speed of the ship or gold coins</li> <li>Add an enemy sprite that when collided with, causes your pirate to lose speed</li> <li>Use one of the phone's sensors to control movement of the pirate ship </li> </ul><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGoldBarcode.png" /></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGold.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <p>Done with <span style="color:black;">GetTheGold</span>? Return to to the other modules <a href="/teach/module-2-2">here</a> or the tutorials <a href="/tutorials">here</a>.</p> </div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/game" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Game</a> </li> <li class="field-item even"> <a href="/tutorial-type/sprites" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Sprites</a> </li> </ul> </section> Fri, 28 Jun 2013 21:35:19 +0000 aaron 346 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/get-gold#comments MoleMash 2 http://dev-explore.appinventor.mit.edu/content/molemash-2 <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } .listblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FCF5D7; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h4 class="ai-header">What You're Building</h4> <p><img src="/sites/all/files/tutorials/moleMash2/front-pic.png" style="float:right;" /></p> <p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch3MoleMash.pdf">Download Refined Version (Book Chapter PDF)</a></p> <p>This tutorial shows you how to build a game similar to the Whac-A-MoleTM arcade game. Specifically, your goal is to whack (tap) a mole that randomly pops out of one of five fixed holes. Every time you succeed, your score is increased by one point.</p> <p>In order to highlight new App Inventor features — the Advanced tab and Sprite Z-layering — this app takes a different approach than the <a href="http://explore.appinventor.mit.edu/content/molemash">original Mole Mash tutorial</a>, which you need not have read in order to do this one. You should, however, be 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 <a href="/tutorials">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Introduction</h4> <p>This tutorial includes:</p> <ol><li>Creating a list of components</li> <li>Using functionality from the Advanced section of the Blocks Editor to get and set properties of arbitrary components</li> <li>Having game events controlled by the <b>Clock</b> component</li> <li>Using Sprite Z-layering to ensure that one sprite (<b>ImageSprite</b> or <b>Ball</b>) appears in front of another</li> </ol><h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Set the screen's <b style="color:green;">Title</b> property to an appropriate name, such as "Mole Mash". Open the Blocks Editor and connect it to the phone. Download these image files (created by Yun Miao) by right-clicking on them, then add them to the project by pressing the "Add..." button in the Media pane.</p> <p><a href="/sites/all/files/tutorials/moleMash2/hole.png"><img src="/sites/all/files/tutorials/moleMash2/hole.png" /></a><a href="/sites/all/files/tutorials/moleMash2/mole.png"><img src="/sites/all/files/tutorials/moleMash2/mole.png" /></a></p> <h4 class="ai-header">Set up the Components</h4> <p>The user interface will contain a total of 6 ImageSprites: 5 unmoving holes and 1 mole, which will move on top of the holes. Use the component designer to create the user interface. When you are done, it should look something like the picture below. Don't worry about lining up the holes evenly. You will specify their locations through their <b style="color:green;">X</b> and <b style="color:green;">Y</b> properties. Additional instructions are below the picture.</p> <p><img src="/sites/all/files/tutorials/moleMash2/designer1.png" /></p> <p>Create the following components by dragging them from the Palette into the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>Canvas</b> </td> <td>Basic</td> <td style="color:green;">GameCanvas</td> <td>The game field</td> </tr><tr><td> <b>ImageSprite</b> (5) </td> <td>Animation</td> <td style="color:green;">Hole1 ... Hole5</td> <td>Holes from which the mole can appear</td> </tr><tr><td> <b>ImageSprite</b> </td> <td>Animation</td> <td style="color:green;">Mole</td> <td>The mole</td> </tr><tr><td> <b>HorizontalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">ScoreArrangement</td> <td>To display the score</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ScoreTextLabel</td> <td>To hold "Score: "</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ScoreValueLabel</td> <td>To hold the score (# of times the mole was hit)</td> </tr><tr><td> <b>Clock</b> </td> <td>Basic</td> <td style="color:green;">MoleClock</td> <td>To control the mole's movement</td> </tr><tr><td> <b>Sound</b> </td> <td>Media</td> <td style="color:green;">Buzzer</td> <td>To vibrate when the mole is touched</td> </tr></table><p>Make the following changes to the components' properties:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component </td> <td> Action </td> </tr><tr><td>Canvas1</td> <td>Set <b style="color:green;">BackgroundColor</b> to Green. Set <b style="color:green;">Width</b> to 320 pixels. Set <b style="color:green;">Height</b> to 320 pixels.</td> </tr><tr><td>Hole1</td> <td>Set <b style="color:green;">X</b> to 20 and <b style="color:green;">Y</b> to 60 (upper left).</td> </tr><tr><td>Hole2</td> <td>Set <b style="color:green;">X</b> to 130 and <b style="color:green;">Y</b> to 60 (upper center).</td> </tr><tr><td>Hole3</td> <td>Set <b style="color:green;">X</b> to 240 and <b style="color:green;">Y</b> to 60 (upper right)</td> </tr><tr><td>Hole4</td> <td>Set <b style="color:green;">X</b> to 75 and <b style="color:green;">Y</b> to 140 (lower left).</td> </tr><tr><td>Hole5</td> <td>Set <b style="color:green;">X</b> to 185 and <b style="color:green;">Y</b> to 140 (lower right).</td> </tr><tr><td>Mole</td> <td>Set <b style="color:green;">Picture</b> to "mole.png". Set <b style="color:green;">Z</b> to 2 so the mole appears in front of the other <b style="color:green;">ImageSprite</b> s, which have the default <b style="color:green;">Z</b> value of 1.</td> </tr><tr><td>ScoreTextLabel</td> <td>Set <b style="color:green;">Text</b> to "Score: ".</td> </tr><tr><td>ScoreTextValue</td> <td>Set <b style="color:green;">Text</b> to "0".</td> </tr></table><p>Don't worry now about setting the <b style="color:green;">Picture</b> property for the holes; we'll set the property in the Blocks Editor.</p> <h4 class="ai-header">Add Behaviors to the Components</h4> <p>Here is an overview of what we need to create blocks to do:</p> <ol><li>Create variables: <ol><li><b style="color:green;">holes</b>: a list of holes</li> <li><b style="color:green;">currentHole</b>: the hole the mole is currently coming out of</li> </ol></li> <li>When the app starts: <ol><li>Populate the list of holes.</li> <li>Set each hole's <b style="color:green;">Picture</b> property to "hole.png".</li> <li>Call procedure <span class="callblock">MoveMole</span> (below).</li> </ol></li> <li>Create a procedure <span class="callblock">MoveMole</span> to: <ol><li>Set <b style="color:green;">currentHole</b> to a random hole from the list <b style="color:green;">holes</b>.</li> <li>Move the mole to the location of <b style="color:green;">currentHole</b>.</li> </ol></li> <li>Make <b>MoleClock</b> call <span class="callblock">MoveMole</span> whenever its timer goes off (every second). </li> <li>Implement a handler that does the following when the mole is touched: <ol><li>Add one to the score.</li> <li>Make the phone briefly vibrate.</li> <li>Call <span class="callblock">MoveMole</span>.</li> </ol></li> </ol><p>To proceed, open the Blocks Editor.</p> <h4 class="ai-header">Creating Variables</h4> <p>Create the variables <b style="color:green;">holes</b> and <b style="color:green;">currentHole</b>. For now, we will give them "dummy" initial values; we'll set their real initial values in the <span class="basicblock">Screen1.Initialize</span> event handler, which is run when the app starts. (For technical reasons, components cannot be referred to in def blocks, which are run before the app has started.) Here is a picture and list of the blocks you will need:</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks1.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="setblock">def variable as</span> (holes)</td> <td>Definition</td> <td>Hold a list of holes.</td> </tr><tr><td><span class="listblock">make a list</span></td> <td>Lists</td> <td>Create an empty list, to be filled in when the program starts.</td> </tr><tr><td><span class="setblock">def variable as</span> (currentHole)</td> <td>Definition</td> <td>Hold the mole's current hole.</td> </tr><tr><td><span class="basicblock">number</span> (0)</td> <td>Numbers</td> <td>Provide a required initial value for <b style="color:green;">currentHole</b>.</td> </tr></table><p>As always, comments (created by right-clicking on a block) are encouraged but not required.</p> <h4 class="ai-header">Starting the App</h4> <p>The first event to occur in any program in <span class="basicblock">Screen1.Initialize</span>, so we will put start-up code in that handler. Specifically, we will add the hole components to the list holes, set each hole's <b style="color:green;">Picture</b> property to "hole.png", and call <span class="callblock">MoveMole</span>. Since we have not yet written MoveMole, we will create an empty procedure with that name, which we will fill in later.</p> <p>Below are a picture and table of the blocks you need to create. Note that the "Any ImageSprite" drawer is found under the "Advanced" tab to the right of "Built-In" and "My Blocks" in the Blocks Editor.</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks2.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Screen1.Initialize</span></td> <td>Screen1</td> <td>Specify what should happen when the app starts.</td> </tr><tr><td><span class="listblock">add items to list</span></td> <td>Lists</td> <td>Add the following values to...</td> </tr><tr><td><span class="argblock">holes</span></td> <td>My Definitions</td> <td>...the list of holes:</td> </tr><tr><td><span class="argblock">component Hole1</span></td> <td>Hole1</td> <td>-the upper left hole</td> </tr><tr><td><span class="argblock">component Hole2</span></td> <td>Hole2</td> <td>-the upper center hole</td> </tr><tr><td><span class="argblock">component Hole3</span></td> <td>Hole3</td> <td>-the upper right hole</td> </tr><tr><td><span class="argblock">component Hole4</span></td> <td>Hole4</td> <td>-the lower left hole</td> </tr><tr><td><span class="argblock">component Hole5</span></td> <td>Hole5</td> <td>-the lower right hole</td> </tr><tr><td><span class="controlblock">foreach</span></td> <td>Control</td> <td>Specify that we would like...</td> </tr><tr><td><span class="argblock">name</span> (hole)</td> <td>Definitions</td> <td>...a variable named "hole"...</td> </tr><tr><td><span class="argblock">holes</span></td> <td>My Definitions</td> <td>...to take on each of the values in the list holes .</td> </tr><tr><td><span class="setblock">ImageSprite.Picture</span></td> <td>Any Image Sprite</td> <td>Set the Picture property of...</td> </tr><tr><td><span class="argblock">value hole</span></td> <td>My Definitions</td> <td>...the ImageSprite referred to by the variable hole ...</td> </tr><tr><td><span class="textblock">text (hole.png)</span></td> <td>Text</td> <td>...to the picture of the empty hole.</td> </tr><tr><td><span class="callblock">to procedure</span> (MoveMole)</td> <td>Definition</td> <td>Create an procedure, to be filled in later, for moving the mole.</td> </tr><tr><td><span class="callblock">MoveMole</span></td> <td>My Definitions</td> <td>Call MoveMole to make the first placement of the mole.</td> </tr></table><p>Compare the <span class="controlblock">foreach</span> block to the equivalent blocks that would be necessary without it:</p> <p><img src="/sites/all/files/tutorials/moleMash2/molemash2.JPG" /></p> <p>Not only is the left set of blocks shorter, it is less repetitious, sparing the programmer from semi-mindless copy-and-pasting and making it easier to modify, for example, if the name of the picture is changed.</p> <h4 class="ai-header">Moving the Mole</h4> <p>Now let's fill in the body of the procedure MoveMole, which we'll call when the program starts, when the mole gets touched, and when our timer goes off every second. What we want it to do is to pick a random hole and move the mole on top of it. Here are a picture and list of the new blocks:</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks4.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="setblock">set currentHole to</span></td> <td>My Definitions</td> <td>Save the...</td> </tr><tr><td><span class="listblock">call pick random item</span></td> <td>Lists</td> <td>...randomly selected...</td> </tr><tr><td><span class="argblock">holes</span></td> <td>My Definitions</td> <td>...hole.</td> </tr><tr><td><span class="basicblock">call Mole.MoveTo</span></td> <td>Mole</td> <td>Move the mole to the...</td> </tr><tr><td><span class="argblock">ImageSprite.X</span></td> <td>Advanced/ImageSprite</td> <td>..x-coordinate of...</td> </tr><tr><td><span class="argblock">currentHole</span></td> <td>My Definitions</td> <td>...the chosen hole...</td> </tr><tr><td><span class="argblock">ImageSprite.Y</span></td> <td>Advanced/ImageSprite</td> <td>...and the y-coordinate of...</td> </tr><tr><td><span class="argblock">current Hole</span></td> <td>My Definitions</td> <td>...the chosen hole.</td> </tr></table><p>We now need to specify that MoveMole should be called whenever MoleClock's Timer goes off. We just need two blocks to accomplish that:</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks5.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">MoleClock.Timer</span></td> <td>MoleClock</td> <td>When the timer goes off...</td> </tr><tr><td><span class="callblock">call MoveMole</span></td> <td>My Definitions</td> <td>...move the mole.</td> </tr></table><h4 class="ai-header">Registering Touches</h4> <p>Finally, we need to specify what happens when the mole is touched. Specifically, we want to:</p> <ol><li>Increment the score.</li> <li>Make the phone vibrate briefly.</li> <li>Move the mole.</li> </ol><p>We can easily translate these to blocks:</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks6.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Mole.Touched</span></td> <td>Mole</td> <td>When the mole is touched...</td> </tr><tr><td><span class="setblock">set ScoreValueLabel.Text to</span></td> <td>ScoreValueLabel</td> <td>...update the visible score to...</td> </tr><tr><td><span class="basicblock"> block</span></td> <td>Math</td> <td>...the result of adding...</td> </tr><tr><td><span class="basicblock">number</span> (1)</td> <td>Math</td> <td>...1 [and]...</td> </tr><tr><td><span class="argblock">ScoreValueLabel.Text</span></td> <td>ScoreValueLabel</td> <td>...the previous score.</td> </tr><tr><td><span class="callblock">call Buzzer.Vibrate</span></td> <td>Buzzer</td> <td>Make the phone vibrate for...</td> </tr><tr><td><span class="basicblock">number</span> (100)</td> <td>Math</td> <td>...100 milliseconds.</td> </tr><tr><td><span class="callblock">call MoveMole</span></td> <td>My Definitions</td> <td>Move the mole to a new location.</td> </tr></table><h4 class="ai-header">Final Program</h4> <p><img src="/sites/all/files/tutorials/moleMash2/blocks-final.png" /></p> <h4 class="ai-header">Variations</h4> <p>Here are some variations you might want to implement:</p> <ul><li>Adding a Reset button to set the score back to 0.</li> <li>Having the score depend not just on the number of hits but also the number of misses and escaped moles.</li> <li>Increasing the speed of the game of mole movement if the player is doing well and decreasing it if the player is doing poorly.</li> <li>Adding a second mole on a different timer.</li> </ul><p>You can see how to implement the first two variations in the <a href="http://explore.appinventor.mit.edu/content/molemash">original Mole Mash tutorial</a>.</p> <h4 class="ai-header">Review</h4> <p>Here are some of the ideas covered in this tutorial:</p> <ul><li>Putting components in a <b>List</b>.</li> <li>Performing an operation on every component in a <b>List</b> using the <span class="controlblock">foreach</span> block and Advanced features.</li> <li>Placing an <b>ImageSprite</b> on top of another, using their <b style="color:green;">Z</b> properties to control which goes in front.</li> <li>Using the <b>Clock</b> component to control game play.</li> <li>Creating a procedure and calling it from multiple places.</li> </ul><pre class="ai-box">Done with <span style="color:black;">MoleMash 2</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/moleMash2/MoleMash2Barcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/moleMash2/MoleMash2.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/moleMash2/MoleMash2.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> </div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/game" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Game</a> </li> <li class="field-item even"> <a href="/tutorial-type/sprites" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Sprites</a> </li> </ul> </section> Wed, 26 Jun 2013 19:45:48 +0000 aaron 338 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/molemash-2#comments VideoWall http://dev-explore.appinventor.mit.edu/content/videowall <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h4 class="ai-header">What you're building</h4> <p>The VideoWall app tutorial demonstrates how you can control the size of a video playing in an app by using the <strong>Video Player</strong> component's <b style="color:green;">Width</b>, <b style="color:green;">Height</b>, and <b style="color:green;">FullScreen</b> features. The VideoWall uses media assets (videos stored in the app itself), but you can use the app to display videos from the internet as well.</p> <p>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 the app's behavior. If you are not familiar with the basics, try stepping through some of the <a href="/tutorials">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name the new project VideoWall and set the screen's Orientation to Landscape.</p> <p>Download the following video files* for use later on:</p> <ul><li><a href="/sites/all/files/tutorials/videoWall/bigbuckbunny.3gp">BigBuckBunny (bigbuckbunny.3gp)</a></li> <li><a href="/sites/all/files/tutorials/videoWall/nasa.3gp">NASA (nasa.3gp)</a></li> <li><a href="/sites/all/files/tutorials/videoWall/sintel.3gp">Sintel (sintel.3gp)</a></li> </ul><p>*Attributions for these videos are included at the end of this tutorial.</p> <h4 class="ai-header">Introduction</h4> <p>The finished VideoWall app will display a wall of three videos that can be expanded to their true size and then shrunk back down again. The app will also allow you to display the videos in fullscreen. This tutorial assumes you have followed earlier tutorials to learn how the following blocks work:</p> <ul><li><span class="argblock">Variables</span></li> <li><span class="callblock">Procedures</span></li> <li><span class="basicblock">Button.Click blocks</span></li> <li><span class="controlblock">Logic (if-else) blocks</span></li> </ul><p>This tutorial introduces the following:</p> <ul><li>Using Advanced blocks</li> <li>Resizing the VideoPlayer</li> <li>Showing the VideoPlayer video in fullscreen mode</li> </ul><h4 class="ai-header">Set up the Components</h4> <p>Use the component designer to create the interface for the <span style="color:green;">VideoWall</span>. When completed, the designer should look similar to the snapshot below.</p> <p><img src="/sites/all/files/tutorials/videoWall/setupcomponents.png" /></p> <p>First, you need to upload the video files. Click on the Add... button and select a video file downloaded earlier. Repeat this step to add the other two video files. Now create the interface by dragging and dropping the components from the Palette to the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>HorizontalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">HorizontalArrangement1</td> <td>Holds all other components: makes the three vertical arrangements line up side by side</td> </tr><tr><td> <b>VerticalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">VerticalArrangement1</td> <td>Holds the left-most VideoPlayer and controls</td> </tr><tr><td> <b>VerticalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">VerticalArrangement2</td> <td>Holds the middle VideoPlayer and controls</td> </tr><tr><td> <b>VerticalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">VerticalArrangement3</td> <td>Holds the right-most VideoPlayer and controls</td> </tr><tr><td> <b>VideoPlayer</b> </td> <td>Media</td> <td style="color:green;">VideoPlayer1</td> <td>Displays the BigBuckBunny video</td> </tr><tr><td> <b>VideoPlayer</b> </td> <td>Media</td> <td style="color:green;">VideoPlayer2</td> <td>Displays the NASA video</td> </tr><tr><td> <b>VideoPlayer</b> </td> <td>Media</td> <td style="color:green;">VideoPlayer3</td> <td>Displays the Sintel video</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResizeButton1</td> <td>Resizes VideoPlayer1</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResizeButton2</td> <td>Resizes VideoPlayer2</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResizeButton3</td> <td>Resizes VideoPlayer3</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">FullScreenButton1</td> <td>Shows the VideoPlayer1 video in fullscreen</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">FullScreenButton2</td> <td>Shows the VideoPlayer2 video in fullscreen</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">FullScreenButton3</td> <td>Shows the VideoPlayer3 video in fullscreen</td> </tr></table><p>Set the properties as described below:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Component</td> <td>Action</td> </tr><tr><td style="color:green;">HorizontalArrangement1</td> <td>Set Width to Fill parent...</td> </tr><tr><td style="color:green;">VerticalArrangement1, VerticalArrangement2, <span style="color:black;">and</span> VerticalArrangement3</td> <td>Set Width to Fill parent...</td> </tr><tr><td style="color:green;">ResizeButton1, ResizeButton2, <span style="color:black;">and</span> ResizeButton3</td> <td>Set Text to "Grow" and set Width to Fill parent...</td> </tr><tr><td style="color:green;">FullScreenButton1, FullScreenButton2, <span style="color:black;">and</span> FullScreenButton3 </td> <td>Set Text to Show FullScreen and set Width to Fill parent...</td> </tr><tr><td style="color:green;">VideoPlayer1</td> <td>Set Source to bigbuckbunny.3gp , set Width to Fill parent... , and set Height to 36 pixels</td> </tr><tr><td style="color:green;">VideoPlayer2</td> <td>Set Source to nasa.3gp , set Width to Fill parent... , and set Height to 36 pixels</td> </tr><tr><td style="color:green;">VideoPlayer3</td> <td>Set Source to sintel.3gp , set Width to Fill parent... , and set Height to 36 pixels</td> </tr></table><h4 class="ai-header">Add Behaviors to the Components</h4> <p>The interface is complete, but the buttons don't resize the videos yet. Open the Blocks Editor to add the behavior to the buttons. First, you'll define three variable blocks to keep track of the size of the VideoPlayers:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="ai-blocks">def variable</span></td> <td>Definition</td> <td>Defines the vid1_zoomed variable (rename it)</td> </tr><tr><td><span class="ai-blocks">def variable</span></td> <td>Definition</td> <td>Defines the vid2_zoomed variable (rename it)</td> </tr><tr><td><span class="ai-blocks">def variable</span></td> <td>Definition</td> <td>Defines the vid3_zoomed variable (rename it)</td> </tr></table><p>The three variables should like this:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/flagblocks.png" /></p> <p>Create the <span class="callblock">resizeVideoPlayer Procedure</span> block. There are three VideoPlayers in the app, but you'll use one Procedure block to resize all three. To accomplish this simplicity, you will use the Advance blocks component <span class="setblock">Any VideoPlayer</span> blocks. Create the <span class="callblock">resizeVideoPlayer Procedure</span> block using the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="ai-blocks">Procedure</span></td> <td>Definition</td> <td>Defines the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">name</span> (x5)</td> <td>Definition</td> <td>Defines the VideoPlayer argument for the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">name</span> (x2)</td> <td>Definition</td> <td>Defines the zoomed argument for the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">name</span> (x3)</td> <td>Definition</td> <td>Defines the button argument for the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">ifelse</span></td> <td>Control</td> <td>Defines the ifelse block that chooses whether the VideoPlayer is shrunk or expanded</td> </tr><tr><td><span class="ai-blocks">=</span> block</td> <td>Logic</td> <td>Defines the equals block for testing if the zoomed block is true</td> </tr><tr><td><span class="ai-blocks">true</span></td> <td>Logic</td> <td>Defines the block that zoomed is compared to</td> </tr><tr><td><span class="ai-blocks">VideoPlayer.Width</span> (x2)</td> <td>Any VideoPlayer</td> <td>Sets the VideoPlayer Width to a number</td> </tr><tr><td><span class="ai-blocks">Number (-1)</span> (x2)</td> <td>Math</td> <td>Width to set VideoPlayer to</td> </tr><tr><td><span class="ai-blocks">VideoPlayer.Height </span> (x2)</td> <td>Any VideoPlayer</td> <td>Sets the VideoPlayer Height to a number</td> </tr><tr><td><span class="ai-blocks">Number</span> (x2), values of 26 and 144</td> <td>Math</td> <td>Height to set VideoPlayer to</td> </tr><tr><td><span class="ai-blocks">Button.text</span></td> <td>Any Button</td> <td>Changes the button text</td> </tr><tr><td><span class="ai-blocks">Text</span></td> <td>Text</td> <td>Text to set button to. Make one text block text's Shrink and the other's Grow.</td> </tr></table><p>The <span class="callblock">resizeVideoPlayer</span> block should look like the following:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/resize_block.png" /></p> <p>The <span class="callblock">resizeVideoPlayer</span> block will be explained later after you create the blocks for responding to button clicks.</p> <h4 class="ai-header">Create the Click Blocks</h4> <p>The blocks you will create respond to clicks on the ResizeButton buttons. To build the three blocks, you will need the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="ai-blocks">ResizeButton1.Click</span></td> <td>ResizeButton1</td> <td>Defines the block for responding to clicks on ResizeButton1</td> </tr><tr><td><span class="ai-blocks">ResizeButton2.Click</span></td> <td>ResizeButton2</td> <td>Defines the block for responding to clicks on ResizeButton2</td> </tr><tr><td><span class="ai-blocks">ResizeButton3.Click</span></td> <td>ResizeButton3</td> <td>Defines the block for responding to clicks on ResizeButton3</td> </tr><tr><td><span class="ai-blocks">ResizeVideoPlayer</span> (x3)</td> <td>My Definitions</td> <td>Starts the resizeVideoPlayer block for resizing a VideoPlayer</td> </tr><tr><td><span class="ai-blocks">not</span> (x3)</td> <td>Logic</td> <td>Defines the block for switching the various zoomed block values</td> </tr><tr><td><span class="ai-blocks">set global vid1_zoomed</span></td> <td>My Definitions</td> <td>Sets the vid1_zoomed block to a different value</td> </tr><tr><td><span class="ai-blocks">set global vid2_zoomed</span></td> <td>My Definitions</td> <td>Sets the vid2_zoomed block to a different value</td> </tr><tr><td><span class="ai-blocks">set global vid3_zoomed</span></td> <td>My Definitions</td> <td>Sets the vid3_zoomed block to a different value</td> </tr><tr><td><span class="ai-blocks">global vid1_zoomed</span></td> <td>My Definitions</td> <td>Used to change the vid1_zoomed value.</td> </tr><tr><td><span class="ai-blocks">global vid2_zoomed</span></td> <td>My Definitions</td> <td>Used to change the vid2_zoomed value.</td> </tr><tr><td><span class="ai-blocks">global vid3_zoomed</span></td> <td>My Definitions</td> <td>Used to change the vid3_zoomed value.</td> </tr><tr><td><span class="ai-blocks">component ResizeButton1</span></td> <td>ResizeButton1</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component ResizeButton2</span></td> <td>ResizeButton2</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component ResizeButton3</span></td> <td>ResizeButton3</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component VideoPlayer1</span></td> <td>VideoPlayer1</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component VideoPlayer2</span></td> <td>VideoPlayer2</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component VideoPlayer3</span></td> <td>VideoPlayer3</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr></table><p>The blocks should look like the following:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/resize_blocks.png" /></p> <p>Most blocks in App Inventor require you to know exactly what component your app will manipulate when you design the app. For some apps, you will have several of the same type of component and you want to program the same behavior for all of the similar components (like the VideoPlayer blocks in this app). The blocks in the Advanced section allow you to build some general manipulation on some type of component. When you built the <span class="callblock">resizeVideoPlayer procedure</span> block, you didn't know specifically which VideoPlayer would be used in the procedure. The <span class="callblock">resizeVideoPlayer</span> works on VideoPlayers; but not until the <span class="callblock">resizeVideoPlayer</span> block is used in the <span class="basicblock">ResizeButton1.Click</span> block (for example) is the specific VideoPlayer known.</p> <p><b>Note:</b> The <span style="color:green;">VideoWall</span> app could have been designed with a specific resizing procedure for each VideoPlayer. By using the Advanced blocks in a single resizing procedure, the app is much simpler.</p> <h4 class="ai-header">How the Blocks Work</h4> <p>Setting the Width and Height property for a VideoPlayer works exactly the same way as setting the Width and Height of a Button. For whatever positive number is set, the video playing will resize its appearance to fit that value. There are two values that are exceptions to the using positive values rule: -1 and -2. Setting VideoPlayer.Width or VideoPlayer.Height to -1 is like setting the Width or Height to <em>Fill parent</em> in the designer. Setting VideoPlayer.Width or VideoPlayer.Height to -2 is like setting the Width or Height to <em>Automatic</em> in the designer.</p> <pre class="ai-warning"><b>Warning:</b> You can set the VideoPlayer Width and Height to any positive number you want. The VideoPlayer will change its size to match the values you set; but on some devices, the VideoPlayer does not change its size correctly. The behavior on such devices is usually unpredictable.</pre><pre class="ai-testing"><b>Test this behavior.</b> Click on the Grow button below the BigBuckBunny video. The video's size should expand, and the text of the button should change to "Shrink". Click on the Shrink button below the BigBuckBunny video. The video's size should shrink back to its original size and the text should change back to "Grow".</pre><h4 class="ai-header">Create the blocks for showing fullscreen video</h4> <p>You will now add the blocks for showing the videos in fullscreen mode. Use the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="ai-blocks">true</span> (x3)</td> <td>Logic</td> <td>Value to set FullScreen as</td> </tr><tr><td><span class="ai-blocks">FullScreenButton1.Click</span></td> <td>FullScreenButton1</td> <td>Responds to clicks on FullScreenButton1</td> </tr><tr><td><span class="ai-blocks">set VideoPlayer1.FullScreen</span></td> <td>VideoPlayer1</td> <td>Used to show fullscreen video</td> </tr><tr><td><span class="ai-blocks">FullScreenButton2.Click</span></td> <td>FullScreenButton2</td> <td>Responds to clicks on FullScreenButton2</td> </tr><tr><td><span class="ai-blocks">set VideoPlayer2.FullScreen</span></td> <td>VideoPlayer2</td> <td>Used to show fullscreen video</td> </tr><tr><td><span class="ai-blocks">FullScreenButton3.Click</span></td> <td>FullScreenButton3</td> <td>Responds to clicks on FullScreenButton3</td> </tr><tr><td><span class="ai-blocks">set VideoPlayer3.FullScreen</span></td> <td>VideoPlayer3</td> <td>Used to show fullscreen video</td> </tr></table><p>The blocks should look like the following:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/fullscreen_blocks.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>The <span class="setblock">VideoPlayer.FullScreen</span> block takes a true/false value (also called a boolean) to tell it whether to go full screen or not. Setting a <span class="setblock">VideoPlayer.FullScreen</span> block to true causes that VideoPlayer to be displayed in fullscreen mode. If there is another VideoPlayer in fullscreen mode, that VideoPlayer's .FullScreen value is set to false and it is replaced with the current VideoPlayer. If a <span class="setblock">VideoPlayer.FullScreen</span> is true, setting a <span class="setblock">VideoPlayer.FullScreen</span> block to false causes the fullscreen mode to be exited and the app's interface to display. Test this behavior. Start playing the BigBuckVideo, and click on the Show FullScreen button below the BigBuckBunny video. The app's interface should disappear and some media controls with the BigBuckBunny video should appear. Use the Back button on your device or the emulator to exit fullscreen. The app's interface should appear.</p> <h4 class="ai-header">Final Program</h4> <p>VideoWall Final Version</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/blockseditor_full.png" /></p> <p>Package the final version of the app by choosing <b>Package For Phone | Barcode</b> from the Component Designer menu. When the barcode appears, use the barcode scanner on your phone to download and install the app. </p> <h4 class="ai-header">Variations</h4> <p>Now that you have finished the first <span style="color:green;">VideoWall</span> app, you might want to build some variations. For example:</p> <ul><li>Get more video files and add a second row to create a real VideoWall</li> <li>Use videos from an online server.</li> <li>Expand the resizeVideoPlayer procedure to resize VideoPlayers by small increments to create an animation effect. You could use multiple Clocks to start the resizeVideoPlayer procedure and animate multiple VideoPlayers at once.</li> </ul><p><b>If you distribute your app to others, make sure you respect any license requirements for the videos you use.</b></p> <p>Below are the attributions to the video files included in this demo app. The creators of the source videos that these clips are from do not endorse App Inventor.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Video File</td> <td>Information</td> <td>Attribution</td> </tr><tr><td>bigbuckbunny.3gp</td> <td>A clip from the full length film</td> <td>(c) copyright 2008, Blender Foundation / <a href="http://www.bigbuckbunny.org">http://www.bigbuckbunny.org</a></td> </tr><tr><td>nasa.3gp</td> <td>A formatted version of the Mars' Whirling Dust Devil clip.</td> <td>Here is the <a>original video.</a></td> </tr><tr><td>sintel.3gp</td> <td>A clip from the full length film </td> <td>(c) copyright Blender Foundation | <a href="http://durian.blender.org">http://durian.blender.org</a></td> </tr></table><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/videoWall/VideoWallBarcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/VideoWall.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/tutorials/videoWall/VideoWall_0.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <pre class="ai-box">MIT is grateful to <a href="http://explore.appinventor.mit.edu/people/vance-turnewitsch">Vance Turnewitsch</a> for developing this tutorial. Done with <span style="color:black;">VideoWall</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/video" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Video</a> </li> </ul> </section> Fri, 14 Jun 2013 16:23:45 +0000 aaron 324 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/videowall#comments StockQuotes http://dev-explore.appinventor.mit.edu/content/stockquotes <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">StockQuotes</span></h2> <h4 class="ai-header">What You're Building</h4> <p>Just like you can access web pages from your phone -- for example, to look up a stock price -- so can App Inventor. This app enables the user to enter a stock symbol, then looks up the price of the stock on Yahoo! Finance and displays the price on the phone.</p> <p>This tutorial assumes that 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 <a href="/tutorials">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Introduction</h4> <p>This tutorial includes</p> <ol><li>Accepting text input from the user to specify the stock symbol.</li> <li>Using the Web component to ask Google Finance for the latest price for the stock.</li> <li>Displaying the result.</li> </ol><h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name it StockQuotes, and also set the screen’s <b style="color:green;">Title</b> to “Stock Quotes”. Open the Blocks Editor and connect it to the phone.</p> <h4 class="ai-header">Set up the Components</h4> <p>Use the component designer to create the user interface. When you are done, it should look something like the picture below. Additional instructions are below the picture.</p> <p><img src="/sites/all/files/tutorials/stockQuotes/components1.png" /></p> <p>Create the following components by dragging them from the Palette into the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">StockSymbolTextBox</td> <td>Where the user enters the stock symbol</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">GetQuoteButton</td> <td>To request the stock quote</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ValueLabel</td> <td>To display the stock quote</td> </tr><tr><td> <b>Web</b> </td> <td>Other stuff</td> <td style="color:green;">Web1</td> <td>To request and receive the stock quote</td> </tr></table><p>Stick with the default properties except for the following changes:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Component</td> <td>Action</td> </tr><tr><td><b>StockSymbolTextBox</b></td> <td>Set its <b style="color:green;">Hint</b> property to "Enter a stock symbol". Clear its <b style="color:green;">Text</b> property by deleting or backspacing over the contents.</td> </tr><tr><td><b>GetQuoteButton</b></td> <td>Set its <b style="color:green;">Text</b> property to "Get Stock Quote".</td> </tr><tr><td><b>ValueLabel</b></td> <td>Clear its <b style="color:green;">Text</b> property.</td> </tr></table><h4 class="ai-header">The Yahoo! Finance API</h4> <p>Many web services provide an <em>application programmer interface</em> (API) for developers to enable their programs to access the service. Some ways to discover APIs are through the website <a href="http://programmableweb.com">http://programmableweb.com</a> or just by doing a web search for the service name and “API”.</p> <p>The Yahoo! Finance API is documented in gory detail at <a href="http://www.gummy-stuff.org/Yahoo-data.htm">http://www.gummy-stuff.org/Yahoo-data.htm</a> . The highlights are that you can get the latest price for the stock with the symbol "GOOG", for example, with the URL <a href="http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=GOOG">http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=GOOG</a> . The section "f=l1" (lower-case letter L, followed by the number 1) says we would like the latest price, and the section “s=GOOG” says we would like information about the stock whose symbol is “GOOG”. The result is returned in comma-separated value (CSV) format, which you may be familiar with from spreadsheets. Since only one value will be returned for our query, the result will be a plain old number, such as “511.5”, without any commas. (Commas would be used if we requested multiple pieces of data from Yahoo!, such as the name of the company and the daily trade volume.)</p> <h4 class="ai-header">Add Behaviors to the Components</h4> <h5 class="ai-header">Requesting the Data</h5> <p>The blocks to make the web request are shown here and detailed below:</p> <p><img src="/sites/all/files/tutorials/stockQuotes/request-data.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">GetQuoteButton.Click</span></td> <td>GetQuoteButton</td> <td>Handle a click of the "Get Quote" button.</td> </tr><tr><td><span class="setblock">set Web1.Url to</span></td> <td>Web1</td> <td>Specify the URL to request.</td> </tr><tr><td><span class="textblock">call make text</span></td> <td>Text</td> <td>Concatenate the parts of the URL.</td> </tr><tr><td><span class="textblock">text</span> (<a href="http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=">http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=</a>)</td> <td>Text</td> <td>Specify the first unchanging part of the URL.</td> </tr><tr><td><span class="argblock">StockSymbolTextBox.Text</span></td> <td>StockSymbolTextBox</td> <td>Get the stock symbol from the text box.</td> </tr><tr><td><span class="callblock">call Web1.Get</span></td> <td>Web1</td> <td>Make the web request.</td> </tr></table><p>The meaning is: When GetQuoteButton is clicked:</p> <ol><li>Build the Web component’s URL by concatenating “<a href="http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=">http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=</a>” (which you should copy and paste into the text block) and the symbol entered by the user (StockSymbolTextBox.Text).</li> <li>Request the page specified by the URL. (This is like pressing return after entering a URL in your web browser.)</li> </ol><h5 class="ai-header">Receiving the Data </h5><p>When the response to the web request arrives, the <span class="basicblock">Web.GotText</span> event is raised with four parameters (only some of which we’ll use in this app):</p> <ol><li><b>url</b>: the URL of the original request (which is useful if requests are made with many different URLs).</li> <li><b>responseCode</b>: <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">the HTTP status code</a>, which indicates whether the web request succeeded or how it failed; for example, 200 means that the request succeeded, 404 that the page could not be found, etc.</li> <li><b>responseType</b>: <a href="http://en.wikipedia.org/wiki/Mime_type">the MIME type</a> of the response, such as “text/csv” in this app, “image/jpeg”, etc.</li> <li><b>responseContent</b>: the data being returned, such as “511.5”.</li> </ol><p>Here are a picture and table of the blocks you need to create:</p> <p><img src="/sites/all/files/tutorials/stockQuotes/receive-data.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Web1.GotText</span></td> <td>Web1</td> <td>Specify what to do when the reply comes back from the web.</td> </tr><tr><td><span class="controlblock">ifelse</span></td> <td>Control</td> <td>Provide different behavior depending on whether the request succeeded.</td> </tr><tr><td><span class="argblock">value responseCode</span></td> <td>My Definitions</td> <td>The response code returned for the web request, which...</td> </tr><tr><td><span class="basicblock"> = </span>(equals) block</td> <td>Math</td> <td>...is checked for equality with...</td> </tr><tr><td><span class="basicblock">number</span> (200)</td> <td>Math</td> <td>...200, the code for valid web responses.</td> </tr><tr><td><span class="setblock">set ValueLabel.Text to</span></td> <td>ValueLabel</td> <td>Display the result on the screen.</td> </tr><tr><td><span class="textblock">call make text</span></td> <td>Text</td> <td>Build the result by concatenating...</td> </tr><tr><td><span class="textblock">text</span> ("Current value: ")</td> <td>Text</td> <td>...the text “Current value: “ and...</td> </tr><tr><td><span class="argblock">value responseContent</span></td> <td>My Definitions</td> <td>...the value returned from the web.</td> </tr><tr><td><span class="setblock">set ValueLabel.Text to</span></td> <td>ValueLabel</td> <td>Display an error message.</td> </tr><tr><td><span class="textblock">text</span> ("Error getting stock quote")</td> <td>Text</td> <td>The error message</td> </tr></table><p>Here's a description of the block's behavior:</p> <ol><li>If the response code indicates that the web request succeeded (= 200), set the label to the concatenation of “Current value: “ and the returned data (e.g., 511.5).</li> <li>Otherwise, set the label to “Error getting stock quote”.</li> </ol><h4 class="ai-header">Review</h4> <p>Here are some ideas introduced in this tutorial:</p> <ol><li>Using an application programmer interface (API)</li> <li>Making a request with the Web component</li> <li>Checking whether a web request was successful</li> <li>Displaying information returned from the web</li> </ol><p>These ideas will be developed further in the second part of this tutorial, which is under development.</p> <h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/stockQuotes/StockQuotesBarcode.png" /></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/tutorials/stockQuotes/StockQuotes.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <h4 class="ai-header">Credits</h4> <pre class="ai-box">This tutorial is based on <a href="http://appinventorblog.com/2011/06/02/app-inventor-has-a-new-component-the-web/">an app created by Prof. David Wolber</a> and relies on the Yahoo! Finance API. Done with <span style="color:black;">StockQuotes</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/external-api" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">External API</a> </li> </ul> </section> Fri, 14 Jun 2013 16:23:17 +0000 aaron 323 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/stockquotes#comments Android, Where's My Car http://dev-explore.appinventor.mit.edu/content/android-wheres-my-car <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">Android, Where's My Car?</span></h2> <p><a href="/sites/all/files/tutorials/wheresMyCar/wheresMyCar.zip"><img src="/sites/all/files/tutorials/wheresMyCar/android-where.jpg" style="float:right; width:250px;" /></a></p> <p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch7AndroidWhere.pdf">Download Refined Version (Book Chapter PDF)</a></p> <p>You parked somewhere near the stadium or bar, but when the concert/party ends you don't have a clue where the car is. The friends you came with are equally as clueless.</p> <p>Fortunately you haven't lost your Android phone that never forgets anything, and you remember you have the hot new app, <span style="color:green;">Android, Where's My Car?</span>. With this app, you click a button when you park your car, and the Android uses its location sensor to record the car's GPS coordinates and address. Later, when you reopen the app, it shows you a map from where you are to the remembered location-- problem solved!</p> <p><a href="http://www.flickr.com/photos/dailylifeofmojo/4128596089/">Photo</a> licensed under <a href="http://creativecommons.org/licenses/by/2.0/deed.en">Creative Commons</a></p> <h4 class="ai-header">Download it, Customize it, Understand it</h4> <p>Below is a customizable, annotated and explained <span style="color:green;">Android, Where's My Car?</span> app. You can:</p> <p><a href="/sites/all/files/tutorials/wheresMyCar/wheresMyCar.zip"><img src="/sites/all/files/tutorials/wheresMyCar/downloadSourcebutton_1.png" style="float:right; width:250px;" /></a></p> <ul><li>Install the app on your phone by scanning a barcode</li> <li>Download the source code blocks for the app, upload them into App Inventor, then customize the app or use it as the basis for another idea you have.</li> <li>Study the annotated blocks and explanations below to better understand the app and App Inventor programming in general.</li> </ul><h4 class="ai-header">Try It</h4> <p>Scan the barcode to your Android phone. It will step you through installing the app.</p> <p>(If you don't have a scanner, download the free ZXing scanner by searching for it at the Android Market)</p> <p><img src="/sites/all/files/tutorials/wheresMyCar/wheresMyCarQRapk.png" /></p> <h4 class="ai-header">Customize It</h4> <p><img src="/sites/all/files/tutorials/wheresMyCar/customize.png" style="float:right;" /></p> <p>Download the source code blocks to create your own customized app.</p> <ol><li>Save the source file (.zip) to your computer (click icon to the right)</li> <li>Do not unzip it-- leave it as a zip file.</li> <li>Open the My Projects page in App Inventor.</li> <li>Select More Actions | Upload Source from the menu.</li> <li>Choose the file you just downloaded</li> </ol><h4 class="ai-header">Understand It</h4> <p>The app demonstrates how to communicate with the Android location sensor, how to record data in the phone's long-term memory (database), and how you can open the Google Maps app from your app to show directions from one one location to another. It makes use of the following App Inventor components:</p> <ul><li><b>Location Sensor</b></li> <li><b>TinyDB</b> -- to store the data</li> <li><b>ActivityStarter</b> -- to open a map</li> </ul><h4 class="ai-header">The User Interface</h4> <p>Here are the components for the <span style="color:green;">Android, Where's My Car?</span> app, as shown in the Component Designer:</p> <p><img src="/sites/all/files/tutorials/wheresMyCar/WheresMyCarDesign.png" /></p> <p>The user interface consists of labels to show location data and buttons to initiate events. Some labels just show static text, e.g., GPSLabel is the text "GPS:" that appears in the user interface. Others, such as CurrentLatLabel, will display dynamic data one the location sensor gets its readings. For these labels, a default value is set (0.0) here in the Component Designer.</p> <p>The ActivityStarter1 component is used to launch the map when the user asks for directions. Its properties are only partially shown above. Here is how they should be specified:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Property</td> <td>Value</td> </tr><tr><td> <b>Action</b> </td> <td>android.intent.action.VIEW</td> </tr><tr><td> <b>ActivityPackage</b> </td> <td>com.google.android.apps.maps</td> </tr><tr><td> <b>ActivityClass</b> </td> <td>com.google.android.maps.MapsActivity</td> </tr></table><h4 class="ai-header">The App's Behavior</h4> <p>Here are the blocks for the <span style="color: green;">Android, Where's My Car</span> app (the yellow annotations will also appear when you load this app into App Inventor):</p> <p><img src="/sites/all/files/tutorials/wheresMyCar/WheresMyCarBlocks.png" /></p> <p>Let's examine the four different event-handlers of the app, starting in the top-left and working around in counter-clockwise order.</p> <p><span class="basicblock">LocationSensor1.LocationChanged</span>: This event occurs when the phone's location sensor first gets a reading, or when the phone is moved to produce a new reading, The event-handler just places the readings--latitude, longitude, and current (street) address-- into the corresponding "Current" labels so that they appear on the phone.The RememberButton is also enabled in this event-handler. Its enabled setting should be unchecked in the Component Designer because there is nothing for the user to remember until the sensor gets a reading.</p> <p><span class="basicblock">RememberButton.Click</span>: When the user clicks the RememberButton , the location sensor's current readings are put into the "remember" labels and stored to the database as well. The DirectionsButton is enabled as it now makes sense for the user click on it to see a map (though it will make more sense once the user changes location).</p> <p><span class="basicblock">DirectionsButton.Click</span>: When the user clicks the DirectionsButton , the event-handler builds a URL for a map and calls ActivityStarter to launch the Maps application and load the map. <span class="textblock">make text</span> is used to build the URL to send to the Maps application. The resulting URL consists of the Maps domain along with two crucial parameters, saddr and daddr , which specify the start and destination for the directions. For this app, the saddr is set to the latitude and longitude of the current location, and the daddr is set to the latitude and longitudeo of the location that was "remembered" (the location of your car!).</p> <p><span class="basicblock">Screen1.Initialize</span>: This event is always triggered when an app opens. To understand it, you have to envision the user recording the location of the car, then closing the app, then later re-opening the app. When the app re-opens, the user expects that the location remembered earlier should appear on the phone. To facilitate this, the event-handler queries the database (<span class="callblock">TinyDB.GetValue</span>). If there is indeed a remembered address stored in the database-- the length of the stored address is greater than zero--the remembered latitude, longitude, and street addres are placed in the corresponding labels.</p> <h4 class="ai-header">Variations</h4> <ul><li>Create "Android, Where is Everyone?", an app that lets a group of people track each other's whereabouts. Whether your hiking or at the park, this app could help save time and even lives.</li> <li>Create a "breadcrumb" app that tracks your (phone's) whereabouts by recording each location change. One interesting refinement would be to only record a new "breadcrumb" if the location has changed by a certain amount.</li> </ul><h4 class="ai-header">Review</h4> <p>Lines and paragraphs break automatically.</p> <p>Here are some of the ideas covered in this tutorial:</p> <ul><li>The <b>LocationSensor</b> component can report the phone's latitude, longitude, and current street address. Its LocationChanged event is triggered when sensor gets its first reading and when the reading changes (the phone has moved).</li> <li>The <b>ActivityStarter</b> component can launch any app including Google Maps. For Maps, you set the DataUri property to the URL of the map you want to display. If you want to show directions, the URL will be of the form: <a href="http://maps.google.com/maps/?saddr=0.1,0.1&amp;daddr=0.2,0.2">http://maps.google.com/maps/?saddr=0.1,0.1&amp;daddr=0.2,0.2</a>, where the numbers are GPS coordinates.</li> <li><span class="textblock">make text</span> is used to piece together (concatenate) separate text items into a single text object. It allows you to concatenate dynamic data with static text. With the Maps URL, the GPS coordinates are the dynamic data.</li> <li><b>TinyDB</b> allows you to store data persistently in the phone's database. Whereas the data in a variable or property is lost when an app closes, the data you store in the database can be loaded into your app each time it is opened.</li> </ul><pre class="ai-box">MIT and Google are grateful to <a href="http://www.appinventor.org/">Professor David Wolber</a>, CS Professor at The University of San Francisco, for developing this tutorial. Done with <span style="color:black;">Android, Where's My Car</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/activity-starter" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Activity Starter</a> </li> <li class="field-item odd"> <a href="/tutorial-type/data-storage" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Data Storage</a> </li> <li class="field-item even"> <a href="/tutorial-type/gps" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">GPS</a> </li> </ul> </section> Fri, 14 Jun 2013 16:21:22 +0000 aaron 322 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/android-wheres-my-car#comments Google Voice for Texting over Wifi http://dev-explore.appinventor.mit.edu/content/google-voice <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">Texting Over Wifi: </span>Using Google Voice</h2> <h4 class="ai-header">Introduction</h4> <p>This tutorial shows how to use the Texting component to send and receive text messages (SMS) over Wifi. This lets<br /> instructors use App Inventor texting examples and exercises with phones that do not have mobile or data plans.</p> <p>In order to use the Texting component over Wifi, the app user will need a <a href="https://www.google.com/voice">Google Voice account</a> and will also need to download and install the <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.googlevoice">Google Voice app</a> from the Play Store.</p> <p>Once you get Google Voice set up on your phone, try the <a href="http://explore.appinventor.mit.edu/content/alertme">AlertMe</a> tutorial.</p> <h4 class="ai-header">Under the Hood: How Things Work</h4> <p>Texting over Wifi uses Google Voice to send and receive messages. The mobile Google Voice app is used for receiving messages and the user's Google Voice account is used for sending messages.</p> <p><b>Receiving a Message:</b></p> <p>Here are some of the internal details for how things work when a message is received.</p> <ol><li>The phone receives an incoming text message, say, "Hi", from some phone, say, "555-111-2222".</li> <li>The Android system forwards the message to the Google Voice mobile app, which has been set up to receive messages.</li> <li>The Google Voice app forwards the message to the Texting component's Broadcast Receiver.</li> <li>If the Texting component is <b>enabled to receive messages</b>, the Broadcast Receiver forwards the message to the Texting component.</li> <li>If the Texting component is running (meaning it is visible in the foreground), its <span class="basicblock">MessageReceived</span> (with the arguments <span class="argblock">555-111-2222</span> and <span class="argblock">Hi</span> for this example) event handler will be invoked.</li> <p><img src="/sites/all/files/tutorials/googleVoiceWifiText/MessageReceivedBlock.png" /></p> <li>The <span class="basicblock">MessageReceived</span> method will process the message according to the algorithm specified in its do slot.</li> </ol><p>Of course most of these details are not visible to the App Inventor programmer, who just needs to worry about the procedure in the Do slot.</p> <p><b>Sending a Message:</b></p> <p>Here are some of the details for how things work when a message is sent.</p> <ol><li>Sending a message requires that the Texting component's <span class="setblock">Message</span> and <span class="setblock">PhoneNumber</span> properties have been set and that its <span class="callblock">SendMessage</span> method has been called.</li> <li>If this is the first message being sent by the app, the user will be prompted to authenticate with their online Google Voice account.</li> <p><img src="/sites/all/files/tutorials/googleVoiceWifiText/sendingmsg.png" /></p> <li>Once authenticated, the <span class="callblock">SendMessage</span> method will forward the message and phone number to Google Voice.</li> <li>Google Voice will forward the message to the destination phone number.</li> </ol><p>Note: if the user sends a message to her own Google Voice number, it will be forwarded back to the phone., which<br /> could be very confusing. This may have implications for how you design your app.</p> <h4 class="ai-header">Preliminaries: Logging onto Wifi</h4> <p>A reliable Wifi hotspot is a prerequisite to using the Texting component without a SIM card or mobile account. Use the phone's <em>Settings &gt; Wireless &amp; networks &gt; Wi-Fi</em> to connect to a Wifi hotspot. This may require you to login to the Wifi with a password and may also require you to login to the school's network with a username and password.</p> <h4 class="ai-header">Setting Up Your Google Voice Account</h4> <p>The revised Texting component uses Google Voice to send outgoing messages over Wifi. In order to build and test an app that sends text messages over Wifi, the app developer will have to have a <a href="https://www.google.com/voice">Google Voice account</a>. Once the app is developed, users of the app will also have to have Google Voice accounts.</p> <p>To create a Google Voice account,</p> <ol><li>Login to your Gmail account.</li> <li>Click on the <em>More</em> tab on the Google menu bar.</li> <li>Select the <em>Even More</em> option.</li> <li>Scroll down to the <em>Google Voice</em> link under <em>Home and Office/<em>.</em></em></li> <li>Follow the instructions there to create a Google Voice number and activate your account.</li> </ol><h4 class="ai-header">Installing the Google Voice App</h4> <p>The revised Texting component receives incoming messages over Wifi through the <a href="http://www.google.com/mobile/voice">Google Voice mobile app</a>. To download and install Google voice on your phone:</p> <ol><li>Start the phone's <em>Market</em> or <em>Play Store</em> app.</li> <li>Search for "Google Voice".</li> <li>Download and install the app.</li> <li>Read and approve the app's permission requests.</li> <li>Start the app and follow the setup instructions.</li> <li>Set the following Google Voice settings under <em>Voice &gt; Sync</em> and notifications:</li> <li>Receive text messages &gt; Via the Google Voice app</li> <li>Text notifications &gt; Off (unless you want your app and Google Voice to notify you)</li> </ol><h4 class="ai-header">Authenticating Outgoing Messages</h4> <p>Because outgoing messages are sent through the user's (online) Google Voice account, users of Texting-over-wifi apps will be asked to give the app permission to access the user's account <b>now and in the future</b>. If there are more than one user account on the phone, the user will first be prompted to choose an account. </p> <table><tr><td><img src="/sites/all/files/tutorials/googleVoiceWifiText/permissionscreen.png" width="200" /></td> <td><img src="/sites/all/files/tutorials/googleVoiceWifiText/authscreen.png" width="200" /></td> </tr></table><p>This description assumes that the user already has an active Google account on the phone. If not, the user will be asked to setup an account or login to an existing Google account.</p> <p>This authentication process will happen the first time the app sends an outgoing message after it is installed. Depending on how the app and phone are used, the user may never again be asked for permission </p> <h4 class="ai-header">In Summary</h4> <p>Congratulations! You have successfully installed Google Voice and are ready to text over Wifi! This will be useful for a variety of Apps that use texting. Now try to build <a href="http://explore.appinventor.mit.edu/content/alertme">AlertMe</a>, an app that allows you to try this new capability.</p> <pre class="ai-box">Done with <span style="color:black;">Google Voice</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/sms-texting" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SMS Texting</a> </li> </ul> </section> Fri, 14 Jun 2013 16:20:49 +0000 aaron 321 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/google-voice#comments No Text While Driving (Part 2) http://dev-explore.appinventor.mit.edu/content/no-text-while-driving-part-2 <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">No Text While Driving</span>, Part 2</h2> <p><img src="/sites/all/files/tutorials/NTWD2/emulator.png" style="float:right; width:350px;" /></p> <p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch4NoTexting.pdf">Download Refined Version (Book Chapter PDF)</a></p> <p>You know that texting while driving is dangerous, so you've created and installed the <a href="http://explore.appinventor.mit.edu/content/no-text-while-driving">No Text While Driving</a> app on your phone. Now, when you drive you open that app and let it auto-respond to incoming texts.</p> <p>But the jingle of the texts coming in is killing you with curiosity-- wouldn't it be great if you could hear the texts spoken aloud? With Part II of the tutorial, you'll extend the app so that it speaks out both the message and who sent it. And since you're making some changes anyway, you'll modify the auto-response so it reports your whereabouts in the reply: "Sorry, I'm driving and I'm at 1600 Pennsylvania Avenue". </p> <p>Before completing this tutorial you should complete <a href="http://explore.appinventor.mit.edu/content/no-text-while-driving">part I</a>.</p> <h4 class="ai-header">Getting Started</h4> <p>For this app to work, you'll need to load a text-to-speech module, <em>Text-To-Speech Extended</em>, on your phone. App Inventor and other apps rely on this module for the underlying voice synthesis. If you don't already have it, you can download onto your phone using the Android Market:</p> <ul><li>On your phone, open the Market app</li> <li>Search for TTS</li> <li>Select the app <em>Text-To-Speech Extended</em> to install</li> </ul><p>Once the <em>Text-To-Speech</em> module is installed, open it to test its features. When it opens, set the default language as desired. Then select "Listen to Preview". If you don't hear anything, make sure the volume on your phone is turned on. You can also change the default Engine which can enhance the quality of the spoken words.</p> <p>Once the Text-To-Speech module is installed and configured as desired, you can use the <b>TextToSpeech</b> component within App Inventor. Begin by opening App Inventor and your <span style="color:green;">NoTextWhileDriving</span> project from part I. SaveAs the project and name the new copy "NoTextWhileDriving2".</p> <h4 class="ai-header">What you'll Learn</h4> <p>The app demonstrates two powerful components:</p> <ul><li>The <b>LocationSensor</b> component to determine the phone's location, and</li> <li>The <b>TextToSpeech</b> component to speak the incoming texts aloud.</li> </ul><p>These components encapsulate some advanced functionality, but using them in building an app is relatively straight-forward.</p> <h4 class="ai-header">Set up the Components</h4> <p>Leave the user interface for <span style="color:green;">NoTextWhileDriving, Part II</span> the same as in Part I. But in the Component Designer, add two non-visual components: a <b>LocationSensor</b> and a <b>TextToSpeech</b> component. You do not need to set any properties of the components.</p> <h4 class="ai-header">Add behaviors to the components</h4> <p>The behavior for part I of No Text While Driving was: "when a text is received, the message the user has put in MessageTextbox is sent as a text message response to the sender."</p> <p>For part II, the behavior will be changed to: "when a text is received, it is spoken aloud and a message, including the text in MessageTextbox and the phone's current location, is sent in response to the sender."</p> <h4 class="ai-header">Speaking the text aloud</h4> <p>When a text message is received by the phone, the <span class="basicblock">Texting.MessageReceived</span> event is triggered. The blocks from Part I handle this event by setting the PhoneNumber and Message properties of the Texting component appropriately and then sending the response text.</p> <p>Extend the blocks from Part I by using the TextToSpeech component to speak both the sender's phone number and the message. You'll add the following blocks to the existing <span class="basicblock">Texting.MessageReceived</span> blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="callblock">TextToSpeech1.Speak</span></td> <td>TextToSpeech1</td> <td>Speak out the message received</td> </tr><tr><td><span class="textblock">make text</span></td> <td>Text</td> <td>Build the words that are to be spoken</td> </tr><tr><td><span class="textblock">text</span> ("message from")</td> <td>Text</td> <td>First words spoken, put a space at end</td> </tr><tr><td><span class="argblock">number</span></td> <td>My Definitions</td> <td>This is the number the original text was received from</td> </tr><tr><td><span class="textblock">text</span> ("")</td> <td>Text</td> <td>Put a space in between number and message</td> </tr><tr><td><span class="argblock">messageText</span></td> <td>My Definitions</td> <td>This is the original message received</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/NTWD2/MessageReceivedSpoken.png" /></p> <h4 class="ai-header">How the blocks work</h4> <p>After the response is sent, the <span class="callblock">TextToSpeech1.Speak</span> function is called. You can plug any text object into the message slot of the Speak function. In this case, <span class="textblock">make text</span> is used to build the words to be spoken, including the text "message from", the phone number from which the message was received (number), a blank text, and the message received (messageText). If the text "hello" was received from the number "111-2222", the words "message from 111-2222. hello." would be spoken.</p> <pre class="ai-testing"><b>Test the behavior.</b> You'll need a second phone to test the behaviors in this app. From the second phone, send a text to the phone that is running the app. Does the second phone speak the text aloud? Does it still send an automated response?</pre><h4 class="ai-header">Adding location information to the auto-response</h4> <p>Next, add a <span class="basicblock">LocationSensor.LocationChanged</span> event handler which places the current address into a variable, lastKnownLocation. When a text comes in, the value of that variable can be added to the response message. Here are the blocks you'll need:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="setblock">def variable</span> (lastKnownLocation)</td> <td>Definitions</td> <td>Create a variable to hold the last read address</td> </tr><tr><td><span class="textblock">text</span> ("unknown")</td> <td>Text</td> <td>Set the default value in case the phone's sensor is not working</td> </tr><tr><td><span class="basicblock">LocationSensor1.LocationChanged</span></td> <td>LocationSensor1</td> <td>This is triggered on the first location reading and every change</td> </tr><tr><td><span class="setblock">set lastKnownLocation to</span></td> <td>My Definitions</td> <td>Set this variable to be used later</td> </tr><tr><td><span class="argblock">LocationSensor1.CurrentAddress</span></td> <td>LocationSensor1</td> <td>This is a street address such as "2222 Willard Street, Atlanta, Georgia"</td> </tr></table><p>Here are the blocks:</p> <p><img src="/sites/all/files/tutorials/NTWD2/lastLocation.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p><span class="basicblock">LocationSensor1.LocationChanged</span> is called the first time the sensor gets a reading and each time the phone is moved enough to trigger a new reading. These blocks just place the current (street) address into the variable lastKnownLocation, which you'll use later when you change the auto-response that is sent out.</p> <h4 class="ai-header">Modify the message with location information</h4> <p>Next, modify the <span class="basicblock">Texting1.MessageReceived</span> event-handler so that the current address is added to the response. You'll need the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="textblock">make text</span></td> <td>Text</td> <td>If there is a location reading, build a compound text object</td> </tr><tr><td><span class="argblock">MessageTextBox.Text </span></td> <td>MessageTextBox</td> <td>This is the (custom) message in the text box</td> </tr><tr><td><span class="textblock">text</span> ( "My location is: ")</td> <td>Text</td> <td>This will be spoken after the custom message (note the leading space)</td> </tr><tr><td><span class="argblock">global lastKnownLocation</span></td> <td>LocatonSensor</td> <td>This is an address such as "2222 Willard Street, Atlanta, Georgia"</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/NTWD2/ReceivedText.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>Instead of directly sending a message of the text in MessageTextbox.Text, the app first builds a message using <span class="textblock">make text</span>. It combines the response text in MessageTextBox.Text with the text " My location is " and then the variable lastKnownLocation.</p> <pre class="ai-testing"><b>Test the behavior.</b> From the second phone, send a text to the phone that is running the app. Does the second phone receive the response text? Does it include location information? </pre><h4 class="ai-header">Final Program</h4> <p><img src="/sites/all/files/tutorials/NTWD2/finalProg.png" /></p> <h4 class="ai-header">Variations</h4> <p>Once you get the app working, you might want to explore some variations. For example,</p> <ul><li>Write a version that lets the user define custom responses for particular phone numbers.</li> <li>Write a version that sounds an alarm when a text is received from a number in a "notify" list.</li> </ul><h4 class="ai-header">Review</h4> <p>Here are some of the ideas covered in this tutorial: </p> <ul><li>The <b>TextToSpeech</b> component takes any text object and speaks it aloud. It relies on an Android module, <em>Text-To-Speech Extended</em>, which must be downloaded to the phone for the app to work.</li> <li><span class="textblock">make text</span> is used to piece together (concatenate) separate text items into a single text object.</li> <li>The <b>LocationSensor</b> component can report the phone's latitude, longitude, and current street address. To ensure that it has a reading, you should access its data in its <span class="basicblock">LocationChanged</span> event-handler, which is triggered the first time a reading is made and on every change thereafter. </li> </ul><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/NTWD2/NTWD2Barcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/NTWD2/notextwhiledriving2.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to customize this sample in App Inventor, download the <a href="/sites/all/files/tutorials/NTWD2/notextwhiledriving2.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <pre class="ai-box">MIT and Google are grateful to <a href="http://www.appinventor.org/">Professor David Wolber</a>, CS Professor at The University of San Francisco, for developing this tutorial. Done with <span style="color:black;">No Text While Driving, Part 2</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/sms-texting" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SMS Texting</a> </li> </ul> </section> Fri, 14 Jun 2013 16:20:14 +0000 aaron 320 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/no-text-while-driving-part-2#comments No Text While Driving http://dev-explore.appinventor.mit.edu/content/no-text-while-driving <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">No Text While Driving</span></h2> <p><img src="/sites/all/files/tutorials/NTWD/screenshot.PNG" style="float:right;" /></p> <p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch4NoTexting.pdf">Download Refined Version (Book Chapter PDF)</a></p> <p>This tutorial demonstrates how an app can respond to text messages automatically. You'll build an app that sends back a response when a text message is received. The idea for the app came from University of San Franciso student Daniel Finnegan.</p> <p>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 <a href="/tutorials">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name it <span style="color:green;">NoTextWhileDriving</span>, and also set the screen's <b style="color:green;">Title</b> to "NoTextWhileDriving". Open the Blocks Editor and connect to the phone.</p> <h4 class="ai-header">Introduction</h4> <p>You'll design the app so that it sends a response to any text message received. You'll also allow the user to customize the response sent.</p> <p>The tutorial introduces the following App Inventor concepts: </p> <ul><li>The <b>Texting</b> component for sending texts and processing received texts.</li> <li>The <b>TinyDB</b> database component for saving the customized message even after the app is closed.</li> </ul><h4 class="ai-header">Set up the Components</h4> <p>The user interface for NoTextWhileDriving is simple: it has a text box for the response message and a button for submitting a change to this message. It also has two checkboxes: one to decide whether or not you want to be receiving messages and one to choose to enable Google Voice. This is useful for texting if your phone doesn't have a SIM card. Visit the <a href="http://appinventor.mit.edu/explore/content/google-voice-texting-over-wifi.html">Texting over Google Voice</a> tutorial to learn more about this.</p> <p>You'll also need a Texting component and a TinyDB component, both of which will appear in the "non-visual" component area. A table of detailed instructions for designing the components is below, but you can also build it from the following picture of what it should look like:</p> <p><img src="/sites/all/files/tutorials/NTWD/fullscreen.png" /></p> <p>The components listed below were used to create the designer window shown above. Drag each component from the Palette into the Viewer and name it as specified below:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> <td> Component Settings </td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">PromptLabel</td> <td>Let the user know how the app works</td> <td>Set the <b style="color:green;">Text</b> to "The text below will be sent in response to all texts while this app is running."</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ResponseLabel</td> <td>Displays what text will be sent to incoming messages.</td> <td></td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">NewResponseTextbox</td> <td>User will enter custom response here</td> <td>Set the <b style="color:green;">Hint </b><p> to "Enter custom response."</p></td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">SubmitResponseButton</td> <td>User clicks this to submit new response</td> <td>Set the <b style="color:green;">text </b><p> to "Submit Response."</p></td> </tr><tr><td> <b>CheckBox</b> </td> <td>Basic</td> <td style="color:green;">CheckBoxReceivingEnabled</td> <td>Let the user choose if they want to receive messages.</td> <td></td> </tr><tr><td> <b>CheckBox</b> </td> <td>Basic</td> <td style="color:green;">CheckBoxGvEnabled</td> <td>Let the user choose if they want to respond using Google Voice.</td> <td></td> </tr><tr><td> <b>Texting</b> </td> <td>Social</td> <td style="color:green;">Texting1</td> <td>The component that processes the texts</td> <td></td> </tr><tr><td> <b>TinyDB</b> </td> <td>Basic</td> <td style="color:green;">TinyDB1</td> <td>The component that will store the response in the database</td> <td></td> </tr></table><h4 class="ai-header">Add behaviors to the components</h4> <p><span style="color:green;">NoTextWhileDriving</span> has the following behaviors:</p> <ol><li>When a text is received, the message displayed in ResponseLabel is sent as a text message response to the sender.</li> <li>When the user modifies the custom message in NewResponseTextbox and clicks the SubmitResponseButton , the new message is saved persisently in the phone's database.</li> <li>When the app begins, the custom message is loaded from the database into ResponseLabel.</li> </ol><h4 class="ai-header">1. Responding to a text</h4> <p>When a text message is received by the phone, the <span class="basicblock">Texting.MessageReceived</span> event is triggered. Your app should handle this event by setting the PhoneNumber and Message properties of the Texting component appropriately and sending the response text.</p> <p>You'll need the following blocks: </p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Texting1.MessageReceived</span></td> <td>Texting1</td> <td>Event-handler triggered when the phone receives a text</td> </tr><tr><td><span class="setblock">set Texting1.PhoneNumber to</span></td> <td>Texting1</td> <td>Set the PhoneNumber property before sending </td> </tr><tr><td><span class="argblock">value number</span></td> <td>My Definitions</td> <td>This is the phone number of the person who sent the text</td> </tr><tr><td><span class="setblock">set Texting1.Message to</span></td> <td>Texting1</td> <td>Set the Message property before sending</td> </tr><tr><td><span class="argblock">ResponseLabel.Text</span></td> <td>ResponseLabel</td> <td>This is the message the user has entered</td> </tr><tr><td><span class="callblock">Texting1.SendMessage </span></td> <td>Texting1</td> <td>Send the message</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/NTWD/messagereceivedblocks.PNG" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>When the phone receives any text message, the <span class="basicblock">Texting1.MessageReceived</span> event is triggered. The phone number of the sender is in the argument number, and the sender's message is in the argument <span class-="">messageText</span>.</p> <p>In response, the app sends a text message to the sender. To send a text, the app sets the two key properties of the Texting component: PhoneNumber and Message. <span class="setblock">Texting.PhoneNumber</span> is set to the number of the sender, and <span class="setblock">Texting.Message</span> is set to the text in <span class="argblock">ResponseLabel</span> -- this might be the default, "I'm driving right now, I'll contact you shortly.", or the user may have modified it. Once these properties are set, <span class="callblock">Texting1.SendMessage</span> is called to actually send the response text message.</p> <p>The <span class="controlblock">if</span> block prevents the app from sending the automatic reply if it receives its own message. This would happen, for example, if the user is texting their own number to test the app.</p> <pre class="ai-testing"><b>Test the behavior.</b> You'll need a second phone to test this behavior. From the second phone, send a text to the phone that is running the app. You can <a href="http://explore.appinventor.mit.edu/content/google-voice">set up one phone with Google Voice</a> or start two emulators to communicate with one another to test this behavior. Does the second phone receive the response text? If that works, try modifying the response message and sending another message from the second phone. Is the new response sent?</pre><h4 class="ai-header">2. Storing the custom response</h4> <p>The app so far works, but if you close the app and reopen it, the custom message will be lost. To make things more convenient for the user, store the custom response message they enter into a database using the TinyDB component.</p> <p>TinyDB provides two blocks: StoreValue and GetValue . The former allows you to store a tagged piece of information, while the latter let's you retrieve one.</p> <p>You'll need the following blocks to store the custom message: </p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">SubmitResponseButton.Click</span></td> <td>SubmitResponseButton</td> <td>User clicks this button to submit new response message</td> </tr><tr><td><span class="setblock">ResponseLabel.Text</span></td> <td>ResponseLabel</td> <td>Sets the response to be what the user inputs.</td> </tr><tr><td><span class="argblock">NewResponseTextbox.Text</span></td> <td>NewResponseTextbox</td> <td>The response message entered by the user is here</td> </tr><tr><td><span class="callblock">TinyDB1.StoreValue</span></td> <td>TinyDB1</td> <td>Store the custom message in the phone's database</td> </tr><tr><td><span class="textblock">text</span> ("responseMessage")</td> <td>Text</td> <td>Use this as the tag for the data</td> </tr><tr><td><span class="argblock">ResponseLabel.Text</span></td> <td>ResponseLabel</td> <td>The response message entered by the user is displayed here after the user submits their new response.</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/NTWD/submitresponse.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>When the user clicks the SubmitResponseButton, the app will store the response message entered by the user as the shown text that will be sent. The text in this label (<span class="argblock">ResponseLabel.Text</span>) will be stored in TinyDB. The text <span class="textblock">responseMessage</span> is used as a tag to uniquely identify the information-- later, you'll use that same tag to retrieve the message from the database.</p> <h4 class="ai-header">3. Retrieving the saved response message</h4> <p>Program the <span class="basicblock">Screen1.Initialize</span> event-handler so that the saved custom response message is retrieved from the database and placed in ResponseLabel. Check the retrieved data to make sure there's something there-- after all, the first time the app is used, the database will not have any message saved. If there is a stored message, place it in the ResponseLabel so that the user can see it and so that it will be used to respond to incoming texts.</p> <p>You'll need the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="setblock">def variable</span> ("response")</td> <td>Definitions</td> <td>A temporary variable to hold the retrieved data </td> </tr><tr><td><span class="textblock">text</span> (blank)</td> <td>Text</td> <td>Initial value for the variable can be anything</td> </tr><tr><td><span class="basicblock">Screen1.Initialize</span></td> <td>Screen1</td> <td>This is triggered when app begins</td> </tr><tr><td><span class="setblock">Texting1.ReceivingEnabled</span></td> <td>Texting1</td> <td>Sets the app so that it receives SMS text messages</td> </tr><tr><td><span class="basicblock">number</span> (3)</td> <td>Number</td> <td>The app is initialized to receive text messages while the app is running or when it's not</td> </tr><tr><td><span class="setblock">CheckBoxGvEnabled.Checked</span></td> <td>CheckBoxGvEnabled</td> <td>Sets status of the Google Voice Enabled checkbox</td> </tr><tr><td><span class="argblock">Texting1.GoogleVoiceEnabled</span></td> <td>Texting1</td> <td>If Google Voice is enabled, SMS messages will be sent over Google Voice</td> </tr><tr><td><span class="controlblock">if else test</span></td> <td>Control</td> <td>To ask if texting should be enabled.</td> </tr><tr><td><span class="basicblock">not= block</span></td> <td>Math</td> <td>Check if the retrieved value is not equal to (=) 1</td> </tr><tr><td><span class="argblock">Texting1.ReceivingEnabled</span></td> <td>Texting1</td> <td>Lets the user decide whether or not the app will received SMS messages</td> </tr><tr><td><span class="setblock">CheckBoxReceivingEnabled.Checked</span>(x2)</td> <td>CheckBoxReceivingEnabled</td> <td>Sets status of the Receiving Enabled checkbox.</td> </tr><tr><td><span class="controlblock">true</span></td> <td>Logic</td> <td>Sets the app to receive text messages</td> </tr><tr><td><span class="controlblock">false</span></td> <td>Logic</td> <td>Sets the app to not receive text messages</td> </tr><tr></tr><tr><td><span class="setblock">set Response</span></td> <td> Definitions </td> <td>Sets the variable to the value retrieved from db.</td> </tr><td><span class="callblock">TinyDB1.GetValue</span></td> <td>TinyDB1</td> <td>Get the stored response text from the database</td> <tr><td><span class="textblock">text</span> ("responseMessage")</td> <td>Text</td> <td>Plug into tag slot of GetValue, make sure text is same as was used in StoreValue above</td> </tr><tr><td><span class="controlblock">if test</span></td> <td>Control</td> <td>To ask if the retrieved value has some text</td> </tr><tr><td><span class="basicblock">&gt; block</span></td> <td>Math</td> <td>Check if length of retrieved value is greater than (&gt;) 0</td> </tr><tr><td><span class="textblock">length test</span></td> <td>Text</td> <td>Check if length of retrieved value is greater than 0</td> </tr><tr><td><span class="argblock">global response</span> (x2)</td> <td>My Definitions</td> <td>This variable holds the value retrieved from GetValue</td> </tr><tr><td><span class="basicblock">number</span> (0)</td> <td>Math</td> <td>To compare with length of response</td> </tr><tr><td><span class="setblock">set ResponseLabel.Text to</span></td> <td>Message</td> <td>If we retrieved something, place it in ResponseLabel</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/NTWD/initializeblock_update.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>When the app begins, the <span class="basicblock">Screen1.Initialize</span> event is triggered. The app calls the <span class="callblock">TinyDB1.GetValue</span> with a tag of <span class="textblock">responseMessage</span>-- the same tag used when you stored the user's entry earlier. The resulting value is placed in the variable <span class="setblock">response</span>. When the app starts, we set the Texting component to have receiving enabled, but not Google Voice, which is displayed on the user interface. <span class="argblock">ReceivingEnabled</span> takes a number value 1 (receiving disabled), 2 (receiving enabled while app is running), or 3 (receiving enabled when app is running and is not running) </p> <p>The variable response is used so that the value returned from the database can be checked. If it has a length of 0, then there was no database entry with a tag of <span class="textblock">responseMessage</span>-- something that will occur the first time a user runs this app. But if the length is greater than 0, the app knows that a custom response has been stored previously, and the retrieved value can be placed in the ResponseLabel which the user will see and which is used as the message for any response texts sent. </p> <pre class="ai-testing"><b>Test the app.</b> Enter a new response message in the NewResponseTextbox and click the SubmitResponseButton. Then restart the app by clicking the Restart App button in the Blocks Editor. This will cause the app to re-initialize just like it will when a user closes the app and reopens it later. Does the custom message you entered appear?</pre><h4 class="ai-header">Selecting Response Settings</h4> <p>The user interface has two checkboxes that the user can toggle: whether Receiving is enabled and whether Google Voice is enabled. The first allows the user to decide whether or not they want to be receiving messages. The second lets the user decide if they want to send messages from their own phone number or from a Google Voice account. When the user toggles these switches, the changes are communicated to the Texting component which enables or disables these properties as marked.</p> <p>You'll need the following blocks.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">CheckBoxGvEnabled.Changed</span></td> <td>CheckBoxGvEnabled</td> <td>Detects if the user toggles this control.</td> </tr><tr><td><span class="setblock">Texting1.GoogleVoiceEnabled</span></td> <td>Texting1</td> <td>Sets whether or not Google Voice is enabled</td> </tr><tr></tr><tr><td><span class="argblock">CheckBoxGvEnabled.Checked</span></td> <td>CheckBoxGvEnabled</td> <td>Returns true or false value.</td> </tr><td><span class="basicblock">CheckBoxReceivingEnabled.Changed</span></td> <td>CheckBoxReceivingEnabled</td> <td>Detects if the user toggles this control.</td> <tr><td><span class="controlblock">if else block</span></td> <td>Control</td> <td>Checks whether or not receiving is enabled.</td> </tr><tr><td><span class="basicblock">= block</span></td> <td>Math</td> <td>Checks whether or not receiving is enabled.</td> </tr><tr><td><span class="basicblock">true</span></td> <td>Logic</td> <td>Checks whether or not receiving is enabled.</td> </tr><tr><td><span class="argblock">CheckBoxReceivingEnabled.Checked</span></td> <td>CheckBoxReceivingEnabled</td> <td>Returns true or false value.</td> </tr><tr><td><span class="setblock">Texting1.ReceivingEnabled</span>(x2)</td> <td>Texting1</td> <td>Sets whether or not receiving is enabled.</td> </tr><tr><td><span class="basicblock">number</span>(1)</td> <td>Math</td> <td>Sets ReceivingEnabled as false.</td> </tr><tr><td><span class="basicblock">number</span>(3)</td> <td>Math</td> <td>Sets ReceivingEnabled as true.</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/NTWD/checkboxblocks_update.png" /></p> <pre class="ai-testing"><b>Test the app.</b> Try texting your Android device when the "Receiving Enabled" is checked and then when it is not checked. Do you receive texts when it is unchecked? Try texting over Google Voice. If any of these features aren't working like you expect them to, go back and look at the blocks again!</pre><h4 class="ai-header">No Text While Driving, Final Program</h4> <p><img src="/sites/all/files/tutorials/NTWD/allblocks.png" /></p> <h4 class="ai-header">Variations</h4> <p>Once you get the No Text While Driving app working, you might want to explore some variations. For example,</p> <ul><li>Write a version that speaks the received texts aloud. You'll need to use the <b>TextToSpeech</b> component.</li> <li>Write a version that lets the user define custom responses for particular phone numbers.</li> <li>Write a version that sends custom responses based on the user's location (e.g., I'm in church...)</li> </ul><h4 class="ai-header">Review</h4> <p>Here are some of the ideas covered in this tutorial: </p> <ul><li>The <b>Texting</b> component can be used both to send text messages and process the ones that are received.</li> <li>The <b>TinyDB</b> component is used to store information persistently, in the phone's database, so that it there each time the app is opened.</li> </ul><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/NTWD/NTWDBarcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/NTWD/NoTextWhileDriving.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/tutorials/NTWD/NoTextWhileDriving.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <pre class="ai-box">MIT and Google are grateful to <a href="http://www.appinventor.org/">Professor David Wolber</a>, CS Professor at The University of San Francisco, for developing this tutorial. Done with <span style="color:black;">No Text While Driving</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/data-storage" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Data Storage</a> </li> <li class="field-item odd"> <a href="/tutorial-type/sms-texting" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SMS Texting</a> </li> </ul> </section> Fri, 14 Jun 2013 16:19:45 +0000 aaron 319 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/no-text-while-driving#comments AlertMe http://dev-explore.appinventor.mit.edu/content/alertme <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">AlertMe: </span>Texting in the background, when app is not running</h2> <p>The <span style="color:green;">AlertMe</span> app receives alert messages, and notifies the user even when the app is not currently running. If the app is running (visible on the screen), when it receives an SMS, the message will be displayed on the screen. If it's not running, the user will receive a <em>Notification</em> in the status bar, which can be viewed by pulling down the status bar. Tapping on the notification will start the app and display the message. The user can then click the <em>Acknowledge</em> button to send an acknowledgment to the sender that the alert has been received.</p> <table><tr><td><img src="/sites/all/files/tutorials/alertMe/notification.png" width="200" /></td> <td><img src="/sites/all/files/tutorials/alertMe/notification%20bar.png" width="200" /></td> <td><img src="/sites/all/files/tutorials/alertMe/alert%20me%20running.png" width="200" /></td> </tr><tr><td colspan="3" align="center"><a href="/sites/explore.appinventor.mit.edu/files/AlertMe.zip"><img src="/sites/explore.appinventor.mit.edu/files/downloadSourcebutton.png" style="float: center;border:none" width="250" /></a></td> </tr></table><pre class="ai-box"><strong>If you are using a device that does not have regular SMS enabled through a cell phone carrier and want to do texting over the internet (IP/wifi)</strong>, make sure you have a Google Voice account and you have the Google Voice app set up on your phone or tablet. For more information on how to do this, see the <a href="http://explore.appinventor.mit.edu/content/google-voice">Google Voice for Wifi Texting</a> tutorial. When you set up the texting component in the designer, be sure you have checked the <em>GoogleVoiceEnabled</em> property.</pre><hr /><h4 class="ai-header">The Designer</h4> <p>The interface of the app is pretty simple. It displays the time, phone number, and message of each of the alerts, as well as an acknowledge button. What really drives this app is the Texting component that you will add. The components are: </p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Component Type</td> <td>Palette Group</td> <td>What you'll name it</td> <td>Purpose of Component</td> </tr><tr><td style="color:green;">Label</td> <td>Basic</td> <td>LabelHeader</td> <td>Displays the "Alerts" header.</td> </tr><tr><td style="color:green;">Label</td> <td>Basic</td> <td>LabelAlerts</td> <td> <p>Displays the incoming messages in a log</p> <p>Set width and height to <b>Fill Parent</b></p> </td> </tr><tr><td style="color:green;">Button</td> <td>Basic</td> <td>ButtonAck</td> <td>Sends an achknowledgment to the alert sender.</td> </tr><tr><td style="color:green;">Clock</td> <td>Basic</td> <td>Clock1</td> <td>Used to generate a time stamp in the message log.</td> </tr><tr><td style="color:green;">Texting</td> <td>Social</td> <td>Texting1</td> <td> <p>Receives and sends messages over Wifi.</p> <p><em>Only if you are using texting over wifi through Google Voice:</em> <b>Check the <em>GoogleVoiceEnabled</em> property.</b></p> </td> </tr></table><p>When you're done, the designer should look like this.</p> <p><img src="/sites/all/files/tutorials/alertMe/designer_0.png" /></p> <h4 class="ai-header">The Blocks Editor</h4> <p>The blocks have to handle two events: receiving a message and sending an acknowledgment. In each of these cases, they have to know who sent the message and what it said. We'll approach each of these actions in turn.</p> <p><b>Variables</b></p> <p>Since both procedures require that we know the alert message and who sent it, we will define two globalvariables: <span class="setblock">alertPhoneNumber</span> and <span class="setblock">alertMessage</span>.</p> <p><img src="/sites/all/files/tutorials/alertMe/variables.png" /></p> <p><b>The Message Received Block</b></p> <p>Incoming messages are handled by the <span class="basicblock">MessageReceived</span> block, which takes two arguments, the <span class="argblock">number</span> and the <span class="argblock">messageText</span>. For this app, we store the values of these arguments in our global variables, <span class="setblock">alertPhoneNumber</span> and <span class="setblock">alertMessage</span> respectively, and then construct a log entry and display it on the label using <span class="setblock">LabelAlerts.Text</span>.</p> <p><img src="/sites/all/files/tutorials/alertMe/AlertMeBlock.png" /></p> <p><b>Sending an Acknowledgment</b></p> <p>The user can acknowledge an alert by sending a message back to the sender. This is done using <span class="basicblock">ButtonAck.Click</span>, which constructs the message and sends it as shown here. </p> <p><img src="/sites/all/files/tutorials/alertMe/buttonclick.png" /></p> <h4 class="ai-header">Variations</h4> <p>Now that you have AlertMe working, here are some variations on the program you can make.</p> <ul><li>Modify the function of the <em>Acknowledge</em> button so you can choose to send different text, such as choosing between "What's up?", "On my way", and "Call you later."</li> <li>Change the blocks so the user gets an automatically generated response (without you clicking a button). This could be a setting you could enable if you are away from your phone or in a meeting.</li> </ul><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/alertMe/AlertMeBarcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/alertMe/AlertMe.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/tutorials/alertMe/AlertMe.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <pre class="ai-box">Done with <span style="color:black;">AlertMe</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/sms-texting" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SMS Texting</a> </li> </ul> </section> Fri, 14 Jun 2013 16:13:33 +0000 aaron 318 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/alertme#comments Broadcast Hub http://dev-explore.appinventor.mit.edu/content/broadcasthub <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } .listblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FCF5D7; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">BroadcastHub</span></h2> <p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch11BroadcastHub.pdf">Download Refined Version (Book Chapter PDF)</a></p> <p>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 <a href="http://www.frontlinesms.com/">FrontLineSMS</a>, a tool that has been used in developing countries to <a href="http://news.bbc.co.uk/2/hi/technology/8209172.stm">monitor elections</a>, broadcast weather changes, and in general connect people that don't have access to the web but do have phones and mobile connectivity.</p> <p>FrontLineSMS 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.</p> <p>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 <a href="http://explore.appinventor.mit.edu/tutorials">basic tutorials</a> before continuing.</p> <p>The tutorial also assumes you have completed the <a href="http://explore.appinventor.mit.edu/content/textgroup">TextGroup</a> tutorial and thus are familiar with the basics of the <b>Texting</b> component.</p> <h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name it <span style="color:green;">BroadcastHub</span>, and also set the screen's <b style="color:green;">Title</b> to "BroadcastHub". Open the Blocks Editor and connect to the phone.</p> <h4 class="ai-header">Introduction</h4> <p>BroadcastHub processes text messages that are received in the following manner: </p> <ul><li>If the text message is from an unknown source, the app responds with a text that invites that source to join the broadcast list.</li> <li>If the text message “joinabc” is received, the app adds the sender to the broadcast list.</li> <li>If the text message is from a number already in the broadcast list, the message is broadcast to all numbers in the list.</li> </ul><p>The tutorial covers the following App Inventor concepts:</p> <ul><li>The <b>Texting</b> component for sending texts and processing received texts.</li> <li>List variables to keep track of the numbers to text.</li> <li>The <span class="basicblock">Clock.Timer</span> block that is used to cause an app to repeat operations on a list of data (the list of phone numbers) each time the Timer goes off</li> </ul><h4 class="ai-header">Setting up the Components</h4> <p>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.</p> <p>For this sample, that user interface is simple: it will display the current <em>broadcast list</em> -- the list of phone numbers which have registered for the service-- and it will report all texts it receives and broadcasts.</p> <p>To build the interface, add the following components:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">BroadcastListLabel</td> <td>This will display the phone numbers that are registered.</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">LogLabel</td> <td>This will display a log of the texts received and broadcast.</td> </tr><tr><td> <b>Texting</b> </td> <td>Social</td> <td style="color:green;">Texting1</td> <td>The component that processes the texts</td> </tr><tr><td> <b>TinyDB</b> </td> <td>Basic</td> <td style="color:green;">TinyDB1</td> <td>To store the list of registered phone numbers</td> </tr></table><ul><li>Set the <b style="color:green;">Width</b> of each of the labels to "Fill Parent" so that they span the phone horizontally. Set the <b style="color:green;">Height</b> for the labels to 200 pixels.</li> <li>Set the <b style="color:green;">Text</b> property of BroadcastListLabel to "Broadcast List...".</li> <li>Set the <b style="color:green;">Text</b> property of LogLabel to blank.</li> </ul><p>BroadcastHub should look like this after its front-end is designed:</p> <p><img src="/sites/all/files/tutorials/broadcastHub/broadcasterDesigner.png" /></p> <h4 class="ai-header">Add behaviors to the components</h4> <p>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:</p> <ul><li>When the text message is from an unknown source, the app responds with a text that invites that source to join the broadcast list.</li> <li>When the text message "joinabc" is received, register the sender as part of the broadcast list.</li> <li>When the text message is from a number already in the broadcast list, the message is broadcast to all numbers in the list.</li> </ul><p>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:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Texting1.MessageReceived</span></td> <td>Texting1</td> <td>Event-handler triggered when the phone receives a text</td> </tr><tr><td><span class="setblock">set Texting1.PhoneNumber to</span></td> <td>Texting1</td> <td>To set the number for the return text</td> </tr><tr><td><span class="argblock">value number</span></td> <td>My Definitions</td> <td>Argument of <span class="basicblock">MessageReceived</span>, it is the phone number of sender </td> </tr><tr><td><span class="setblock">set Texting1.Message</span></td> <td>Texting1</td> <td>To set the invite message to send</td> </tr><tr><td><span class="textblock">text</span></td> <td>Text</td> <td>The invite message</td> </tr><tr><td><span class="callblock">Texting1.SendMessage</span></td> <td>Texting1</td> <td>Send it!</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/broadcastHub/messageRcvd1.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p><span class="basicblock">Texting1.MessageReceived</span> 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.</p> <pre class="ai-testing"><b>Test the behavior.</b> 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.</pre><h4 class="ai-header">Handling the "joinabc" text message</h4> <p>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:</p> <p><img src="/sites/all/files/tutorials/broadcastHub/BroadcastList.png" /></p> <p>Next, modify the <span class="basicblock">Texting1.MessageReceived</span> 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:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="controlblock">ifelse</span></td> <td>Control</td> <td>Depending on message received, you'll do different things</td> </tr><tr><td>= block</td> <td>Math</td> <td>The test will be: is messageText equal to "joinabc"</td> </tr><tr><td><span class="argnumber">value messageText</span></td> <td>My Definitions</td> <td>Plug into = block</td> </tr><tr><td><span class="textblock">text</span> ("joinabc")</td> <td>Text</td> <td>Plug into = block</td> </tr><tr><td><span class="listblock">add items to list</span></td> <td>Lists</td> <td>To add the sender's number to BroadcastList</td> </tr><tr><td><span class="argblock">BroadcastList</span></td> <td>My Definitions</td> <td>The list</td> </tr><tr><td><span class="argblock">value number</span></td> <td>My Definitions</td> <td>Plug in as item of <span class="listblock">add items to list</span></td> </tr><tr><td><span class="setblock">set BroadcastListLabel.Text to</span></td> <td>BroadcastListLabel</td> <td>Display the new list</td> </tr><tr><td><span class="argblock">BroadcastList</span></td> <td>My Definitions</td> <td>Plug in to <span class="setblock">set BroadcastListLabel.Text to</span> block</td> </tr><tr><td><span class="setblock">set Texting1.Message to</span></td> <td>Texting1</td> <td>Prepare Texting1 to send message back to sender</td> </tr><tr><td><span class="textblock">text</span> ("congrats, you ...")</td> <td>Text</td> <td>Congratulate sender for joining group</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/broadcastHub/addtolist.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>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 <span class="controlblock">ifelse</span> block, the reply message is sent (bottom row).</p> <pre class="ai-testing"><b>Test this behavior.</b> 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.</pre><h4 class="ai-header">Broadcasting Messages</h4> <p>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 <span class="controlblock">ifelse</span> block to check if the number is in the list, and a <span class="basicblock">Clock.Timer</span> block to broadcast the message to each item in the list. Here are all the blocks you'll need:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="controlblock">ifelse</span></td> <td>Control</td> <td>Depending on whether sender is already in list, you'll do different things</td> </tr><tr><td><span class="listblock">is in list?</span></td> <td>Lists</td> <td>Checks to see if something is in a list</td> </tr><tr><td><span class="argblock">global BroadcastList</span></td> <td>My Definitions</td> <td>Plug into list slot of is in list?</td> </tr><tr><td><span class="argblock">value number</span></td> <td>My Definitions</td> <td>Plug into list slot of is in list?</td> </tr><tr><td><span class="controlblock">Clock.Timer</span></td> <td>My Blocks</td> <td>To repeatedly send out message to all in list</td> </tr><tr><td><span class="argblock">global BroadcastList</span> x2</td> <td>My Definitions</td> <td>Plug into list slot of <span class="controlblock">select list item</span></td> </tr><tr><td><span class="setblock">set Texting1.Message to</span></td> <td>Texting1</td> <td>To set the message</td> </tr><tr><td><span class="argblock">value messageText</span></td> <td>My Definitions</td> <td>The message that was received and to be broadcast</td> </tr><tr><td><span class="setblock">set Texting1.Message to</span></td> <td>Texting1</td> <td>To set the phone number</td> </tr><tr><td><span class="basicblock">set Clock.TimerEnabled</span> x2</td> <td>Clock1</td> <td>To turn the timer on/off</td> </tr><tr><td><span class="basicblock">set nTicks</span> x2</td> <td>My Definitions</td> <td>Sets the value of nTicks</td> </tr><tr><td><span class="controlblock">select list item</span></td> <td>Control</td> <td>To grab an item from the list</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/broadcastHub/textingreceived.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>We've just set up a <span class="controlblock">timer</span> to send a text message to each number in the list, BroadcastList. </p> <pre class="ai-box">A <span class="controlblock" style="color;black;">timer</span> performs some action each time the clock ticks. To control the timer, define a global variable named <b>nTicks</b>. We will set this variable initially to the number of phone numbers in the list. And then we will subtract 1 from the variable each time we send a message. A <span class="controlblock" style="color;black;">timer</span> is done in two parts. In <span class="basicblock">TextingMessage1.Received</span> we will no longer send the message. Instead, we will initialize the global <span class="controlblock">nTicks</span> variable to the length of the <span class="controlblock">BroadcastList</span> list. And we will enable the <span class="controlblock">Clock1</span>. The second part is done using a <span class="controlblock">Clock1.Timer</span> block. This block will contain the <span class="controlblock">Texting1.SendMessage</span> command. Each time the clock ticks the following steps will be performed: </pre><ul><li>Select a number from the <span class="controlblock">phoneNumbers</span> list using the <span class="controlblock">nTicks</span> as the index.</li> <li>Set the <span class="controlblock">Texting1.PhoneNumber</span> to the selected number.</li> <li>Send the text message using <span class="controlblock">Texting1.SendMessage</span>.</li> <li>Subtract 1 from the <span class="controlblock">nTicks</span> variable.</li> <li>If the <span class="controlblock">nTicks</span> is less than or equal to 0, disable the clock</li>. This will stop the timer. </ul><p>The behavior is complex enough that it requires a "nested" <span class="controlblock">ifelse</span> block. If the phone number of the received message is already in the list, the <span class="controlblock">foreach</span> 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 <span class="controlblock">ifelse</span> block: is the messageText equal to "joinabc". The app then branches one of two ways based on the answer.</p> <p>In general, <span class="controlblock">if</span> and <span class="controlblock">ifelse</span> blocks can be nested to arbitrary levels, giving you the power to program arbitrarily complex behaviors.</p> <pre class="ai-testing"><b>Test this behavior.</b> 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.</pre><h4 class="ai-header">Logging the broadcasted texts</h4> <p>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.</p> <p>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".</p> <p>There are two functions in the Text drawer to build text. One is the join function, which joins two pieces of text. Another function, <span class="textblock">make text</span>, 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:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="setblock">set LogLabel.Text to</span></td> <td>LogLabel</td> <td>Display the log here</td> </tr><tr><td><span class="textblock">make text</span></td> <td>Text</td> <td>Build a text object out of multiple parts</td> </tr><tr><td><span class="textblock">text</span> ("message from")</td> <td>Text</td> <td>Report message</td> </tr><tr><td><span class="argblock">value number</span></td> <td>My Definitions</td> <td>The number of the sender</td> </tr><tr><td><span class="textblock">text</span> ("broadcast\n")</td> <td>Text</td> <td>Text is "message from 111-2222 broadcast" with newline</td> </tr><tr><td><span class="argblock">LogLabel.Text</span></td> <td>LogLabel</td> <td>Add new log to the previous ones</td> </tr></table><p>The blocks should look like this:</p> <p><img src="/sites/all/files/tutorials/broadcastHub/broadcastit.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>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 <span class="textblock">make text</span> will build the text object:</p> <p>message from: 1112222 broadcast</p> <p>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.,</p> <p>message from: 1112222 broadcast<br /> message from: 555-6666 broadcast</p> <h4 class="ai-header">Storing the BroadcastList in a Database</h4> <p>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 <b>TinyDB</b> 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. </p> <p>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. </p> <p>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: </p> <ol><li>Drag out a <span class="callblock">TinyDB1.StoreValue</span> block from the TinyDB1 drawer.</li> <li>Create a <span class="textblock">text</span> block and give it the text "broadcastList". Place this text block as the tag of StoreValue.</li> <li>Drag out a reference to BroadcastList from My Definitions . Place it as the value argument of StoreValue.</li> <li>Place the StoreValue block right below the blocks that add an item to the BroadcastList.</li> </ol><p>The bottom part of the modified <span class="basicblock">Texting1.MessageReceived</span> event-handler should look like the following:</p> <p><img src="/sites/all/files/tutorials/broadcastHub/storeBroadcastList.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p><span class="callblock">TinyDB1.StoreValue</span> 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.</p> <h4 class="ai-header">Loading the BroadcastList from a Database</h4> <p>Now add the blocks for loading the list back in each time the app begins. When the app begins, the <span class="basicblock">Screen1.Initialize</span> event is triggered, so your blocks will go in that event-handler. You’ll call <span class="callblock">TinyDB.GetValue</span>, 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.</p> <p>The blocks should look like:</p> <p><img src="/sites/all/files/tutorials/broadcastHub/getValue.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>The blocks first define a variable, valueFromDB, which is used to temporarily store the data returned from the database. When the app begins, the <span class="basicblock">Screen1.Initialize</span> event is triggered. <span class="callblock">TinyDB.GetValue</span> is called, and the data from the database is placed in valueFromDB.</p> <p>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.</p> <p>If valueFromDB is a list, the list is placed into the variable BroadcastList and the list is displayed.</p> <pre class="ai-testing"><b>Test this behavior.</b> Choose <b>Restart App</b> which will trigger the <span class="basicblock" style="color:black;">Screen1.Initialize</span>. Do the numbers registered earlier appear?</pre><h4 class="ai-header">Display BroadcastList with each number on separate lines</h4> <p>Create a procedure <span class="callblock">displayBroadcastList</span>, which displays the list with each phone number on a separate line. Be sure and call the procedure from below the <span class="listblock">add items to list</span> block so that the updated list is displayed.</p> <p>For help displaying the list on separate lines, see <a href="/content/displaying-list">Displaying a List</a>.</p> <p>You'll need the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="callblock">procedure</span> ("displayBroadcastList")</td> <td>Definitions</td> <td>Create the procedure</td> </tr><tr><td><span class="setblock">set BroadcastListLabel.Text to</span></td> <td>BroadcastListLabel</td> <td>Display the list here</td> </tr><tr><td><span class="textblock">text</span> ("Phone Numbers...")</td> <td>Text</td> <td>The header for the list</td> </tr><tr><td><span class="controlblock">foreach</span></td> <td>Control</td> <td>Iterate through the numbers</td> </tr><tr><td><span class="argblock">name pnumber</span></td> <td>in the <span class="controlblock">foreach</span></td> <td>Name the <span class="controlblock">foreach</span> variable "pnumber". This is the current item of the <span class="controlblock">foreach</span></td> </tr><tr><td><span class="argblock">BroadcastList</span></td> <td>My Definitions</td> <td>Plug into in list slot of <span class="controlblock">foreach</span></td> </tr><tr><td><span class="setblock">set BroadcastListLabel.Text to</span></td> <td>BroadcastListLabel</td> <td>Modify with each of the numbers</td> </tr><tr><td><span class="textblock">make text</span></td> <td>Text</td> <td>Build a text object from multiple parts</td> </tr><tr><td><span class="argblock">BroadcastListLabel.Text</span></td> <td>BroadcastListLabel</td> <td>Add to the label on each iteration of <span class="controlblock">foreach</span></td> </tr><tr><td><span class="textblock">text</span> ("\n")</td> <td>Text</td> <td>Newline character so that next number is on next line</td> </tr><tr><td><span class="argblock">value pnumber</span></td> <td>My Definitions</td> <td>The current number from the list</td> </tr></table><p>The <span class="callblock">displayBroadcastList</span> procedure should look like this:</p> <p><img src="/sites/all/files/tutorials/broadcastHub/displayBroadcastList.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>The <span class="controlblock">foreach</span> in <span class="callblock">displayBroadcastList</span> successively adds a phone number to the end of the label, placing a newline character in between each item.</p> <p>Of course this procedure will not do anything unless you call it: you should add two calls to the procedure: one within the <span class="basicblock">Texting1.MessageReceived</span> event-handler, and one within the <span class="basicblock">Screen1.Initialize</span> event-handler. The call <span class="callblock">displayBroadcastList</span> 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 <span class="callblock">displayBroadcastList</span> should look in the snapshot of the final version below.</p> <pre class="ai-testing"><b>Test this behavior.</b> Try adding some more phone numbers to the list. Do the registered phone numbers now appear on separate lines?</pre><h4 class="ai-header">Broadcast Hub, Final Version</h4> <p><img src="/sites/all/files/tutorials/broadcastHub/allBlocks.png" /></p> <h4 class="ai-header">Variations</h4> <p>Once you get the Broadcast Hub app working, you might want to explore some variations. For example,</p> <ul><li>Allow client phones to remove themselves from the list by texting "quitabc" to the app.</li> <li>Let the hub administrator (the user of your app) add and remove numbers from the broadcast list.</li> <li>Let the hub administrator specify numbers that should not be allowed into the list.</li> </ul><h4 class="ai-header">Review</h4> <p>Here are some of the ideas covered in this tutorial: </p> <ul><li>Apps can react to events, like a text being received, that are not initiated by the user of the app.</li> <li>Nested <span class="controlblock">ifelse</span> and <span class="controlblock">foreach</span> blocks can be used to code complex behaviors.</li> <li>The <span class="textblock">make text</span> block can be used to build a text object out of multiple parts.</li> <li><b>TinyDB</b> can be used to store and retrieve data from a database. A general scheme is to call <span class="callblock">StoreValue</span> to update the database whenever the data changes, and call <span class="callblock">GetValue</span> to retrieve the database data when the app begins.</li> </ul><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/broadcastHub/broadcastHubBarcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/broadcastHub/broadcastHub.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/broadcastHub/broadcastHub.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <pre class="ai-box">MIT and Google are grateful to <a href="http://www.appinventor.org/">Professor David Wolber</a>, CS Professor at The University of San Francisco, for developing this tutorial. Done with <span style="color:black;">BroadcastHub</span>? Return to the other tutorials <a href="http://explore.appinventor.mit.edu/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/data-storage" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Data Storage</a> </li> <li class="field-item odd"> <a href="/tutorial-type/sms-texting" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SMS Texting</a> </li> </ul> </section> Fri, 14 Jun 2013 16:13:05 +0000 aaron 317 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/broadcasthub#comments