Professional Documents
Culture Documents
App Inventor Text
App Inventor Text
<Title>
2010 Baseball Forecaster (Ron Shandler's Baseball
Forecaster)
</Title>
</ItemAttributes>
<Items>
<ItemSearchResponse>
The response has a list of items, and each item has a set of tagged
attributes including title, ISBN, etc. The XML is much easier to parse
compared to HTML and the expectation is that it won't change without the
source site giving ample warning (and they don't need to change it for
stylistic reasons, as with the HTML interface).
So a mashup program can call the amazon API, and perhaps call other APIs
such as the Google Books API or a library's API. After the program parses
the XML, the various data is all stored in the program's memory. It can then
process it, organize it, and eventually display it in any manner it would like.
If its goal is to sell books, Amazon provides methods for allowing custom
book sites to earn money on click-throughs.
Here's how product advertising works, from Amazon web site:
1
Your application uses the Product Advertising API to supply item
descriptions and images, and customer and seller reviews, which you
present to your customers.
2Customers shop on your web site.
3
When the customer is ready to purchase the items in their e-commerce
shopping cart, your application sends an HTML form to Product Advertising
API and Amazon completes the purchase by getting purchase information,
such as payment method and shipping address, and then Amazon fulfills
the order by shipping the items.
http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/
Some APIs are simple than Amazon's. For instance, Yahoo provides financial
information with a URL that returns simple comma separated data. For
instance, the URL:
http://download.finance.yahoo.com/d/
quotes.csv?f=sl1d1t1c1ohgv&e=.csv&s=IBM
returns the text:
"IBM",75.97,"11/19/
2008","4:01pm",-4.11,79.93,81.00,75.73,12606807
The API specification is simply this: the commas separate these nine pieces
of information:
Ticker symbol
Last price (after a 20-minute delay)
Date of that price
Time of that price
Change since the day's opening
Opening price
Day's high price
Day's low price
Trade volume
Mashups
The term mashup perhaps originated in the music field, with Eminem's
album The Slim Shady LP combining samples from various other songs and
artists.
Today, numerous sites like ccmixter help artists mashup samples and create
new art. Combining previously created art is controversial of course, due to
copyright issues. For a great introduction to the general concept of mashups
and the societal implications, see Lawrence Lessig's book Remix (you can
find it for free on-line at http://www.bloomsburyacademic.com/remix.htm)
Just as music can be remixed, so can web programs and information. To a
programmer, a mashup is a program that takes data from multiple sources
(APIs) and combines it in interesting ways. Custom bookshops that combine
data from multiple APIs would be considered mashups, but there are many,
many more that use APIs from all walks of life. The site
http://www.programmableweb.com/ provides a dynamic list of interesting
APIs and mashups. Perhaps the most popular example, and one of the first,
is housingmaps.com which combines data from craigslist.com and Google's
maps API. Here's a snapshot of it showing craigslist listings plotted onto a
map of San Francisco:
Tweeting Big Stock Swings To Twitter
Another interesting example of a mashup was provided by Bob DuCharme at
http://www.devx.com/webdev/Article/40511/0/page/1. Bob combined
Yahoo's stock information with the Twitter API to create a mashup that
twitters him when a particular stock has a swing of 50 or more points. This
diagram illustrates how it works:
In this mashup, DuCharme's server program requests data from Yahoo
Finance, which returns it in comma-separated value format. His program
then processes it by checking it against its previous readings. If there is
more than a 50 point difference, it uses the Twitter API to change the status
on his twitter page. Bob and other humans can then check his twitter page
for updates.
RSS
RSS stands for Really Simple Syndication. RSS is a specific XML language
that is used by most blogs and in general any service that just needs to send
out a simple list of items in an XML format.
Because RSS is so common, there are many clients and code libraries for
processing RSS data, so you can help people access your data by putting it
in this format. Note, however, that RSS is a fixed protocol-- if you have
custom data you either have to fit it into RSS fields or define your own XML
schema. For instance, the XML returned by Amazon, shown above, is not in
RSS because Amazon provides pricing and other information that doesn't fit
into the RSS protocol.
Creating Mashups
Mashups are generally created in high-level programming languages such as
Python, Java, or Perl. Most information sources generally provide client
library code in these popular languages that makes data access easy. In
general, however, creating mashups requires sophisticated programming
knowledge.
There have been some advancement in tools for "end-user" creation of
mashups. The term end-user in this context means someone who doesn't
know how to program in a traditional textual language such as Python or
Java (which includes most of the world).
Yahoo Pipes is one such end-user tool. With it, you can link various web
services and RSS data sources together to create mashups. Here's an
example of a pipe that mashes NY City apartment information with user
input:
This pipe allows the user to enter a NYC neighborhood, a keyword, and a
minimum distance. In the sample shown, the user is looking for apartments
near a park in Manhattan.
The pipe was created without any programming, at least of the traditional
textual kind. Here is what development looks like:
The developer just drags in functional nodes for getting user input,
extracting data from sources, fitering, and displaying data. In the sample,
for instance, the top node prompts the user for the neighborhood (the
"where"), then funnels that information to a URL builder that creates a call
to the API http://newyork.backpage.com/online/exports/Rss.xml. The
results are then filtered by location and another input by the user, "what"
(by default, the "what" is "park", but the user can enter any place for which
they'd like to find an apartment that is near).
Sergey Brin Quote, stats about more computer->computer communication
than human-communication
Twitter API
Twitter has an API that return data in RSS format. For instance, one of the
API commands returns the public timeline (the newest twits from the world).
if you enter:
http://twitter.com/statuses/public_timeline.rss
in a browser, the browser will render something like:
This is just because most browsers will render RSS in a format that's nice for
viewing content. Really, the RSS sent to the browser looks like:
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
xmlns:georss="http://www.georss.org/georss">
<channel>
<title>Twitter public timeline</title>
<link>http://twitter.com/public_timeline</link>
<atom:link type="application/rss+xml" href="http://twitter.com/
statuses/public_timeline.rss" rel="self"/>
<description>Twitter updates from everyone!</description>
<language>en-us</language>
<ttl>40</ttl>
<item>
<title>Juliana_Madeira: "É triste pensar que a natureza
fala e que o gênero humano não a ouve." Victor
Hugo</title>
<description>Juliana_Madeira: "É triste pensar que a
natureza fala e que o gênero humano não a ouve."
Victor Hugo</description>
<pubDate>Wed, 20 Jan 2010 20:10:23 +0000</pubDate>
<guid>http://twitter.com/Juliana_Madeira/statuses/
7998009238</guid>
<link>http://twitter.com/Juliana_Madeira/statuses/7998009238</link>
</item>
and the browser has processed it to render it.
This URL returns a particular person's friend timeline:
http://twitter.com/statuses/friends_timeline.xml
If you type this command in a browser, it will prompt for a valid twitter
username and password. You can also enter a URL of the form:
http://username:password@twitter.com/statuses/friends_timeline.xml
replacing "username" and "password" with your own authentication.
Putting REST URLs directly in a browser gives you an idea of how an API
works, but generally these requests will come not from a person, but from a
program. Your program will make an HTTP request, generally using high-
level "client" library code for the particular language you are using, and
hiding the URL details. The library code also takes care of parsing the XML
returned from the service, providing your client with an easy-to-process list
of data.
An App Inventor Twitter Client for Android
An Android programmer, using the Java SDK, could communicate with any
API. App Inventor, however, does not yet provide blocks for calling an
arbitrary API. It does, however, provide blocks for communicating with the
Twitter API.
The blocks consist of request blocks and request-received blocks. Request
blocks are used to send requests to the Twitter API: a request to login, a
request to get the friends_timeline, etc. Typically these requests will be
made from within some event-handler (e.g., when the user clicks a button
labeled "view friends timeline".
Requests are not processed immediately-- when you request a timeline, for
instance, the timeline is not provided as the return value of the block.
Instead, request and reply are asynchronous. You send the request with one
block, then specify an event-handler that will be triggered when the app
receives the request from Twitter.
This separation of request and reply is mandated by the Android system, as
Android wants apps to always be ready to respond to external events,
instead of waiting for some external request to complete.
Here's some program blocks that make use of two request-->handle event
sequences:
In these blocks, we first make a Login request to Twitter. While this
interaction is occurring, the program could handle other user or external
events. When Twitter logs the user in, it sends notification back to the phone
app, and the IsLoggedIn event occurs, triggering the corresponding event-
handler. The programer has set things up so that, in the handler for
"IsLoggedIn", it issues another request with RequestFriendTimeline block.
Once again the app is free to handle other events while Twitter is doing its
job. When Twitter returns the timeline, the FriendTimelineReceived event
occurs, and the program processes it by displaying the information.
Problems
0. Create a mashup using Yahoo Pipes
1. If you don't have a Twitter account, register and get one. If you have one
already, you may want to register with another account for the tutorials we'll
be doing.
2. Add at least one status message on the account, and follow at least one
person and get at least one person to follow you.
3. On your phone, download an Android Twitter client and post a status
message from it. What features does the Twitter Client you chose provide?
Provide a screenshot of your Twitter Client and a description of its features
4. Now create a Twitter Client of your own using App Inventor. You can do
so using the tutorial at: http://sites.google.com/site/appinventorhelp/
tutorials/twitterdemo
5. Write an Android application that combines texting and twitting. For
instance, the app might text one of your friends when you've added a new
status message on Twitter. You don't have to do exactly this-- be creative!
Chapter 10: Persistent Data
Most interesting apps keep track of data over time, usually in some type of
database. App Inventor provides two components, TinyDB and TinyWebDB,
which allow your app to put things in a database and retrieve them later.
This app discusses these components.
** Note: This text was written before the TinyDB component was added to
App Inventor. TinyDB lets you store/retrieve data to persistent storage that
lives directly on the phone. TinyWebDB stores/retrieves to a web database.
TinyDB is simpler-- you just StoreValue tag-value pairs, and call GetValue to
get them back. With TinyWebDB storing is the same, but to retrieve data
you request with GetValue and then let the GotValue event handle things
when the data arrives. But since the data lives off the particular phone,
TinyWebDB can be used for sharing amongst phones/apps (e.g., multi-
player games).
** End Note **
The apps we've looked at so far have used only transient data. Transient
data is short-term: it is initialized when an app begins, and it "dies" when
the app ends. It exists only within a particular phone and a particular
instance of an app.
Consider, for instance, the quiz app discussed previously. The quiz questions
(and answers) are stored in a list. The list of questions is always the same
for every run of the app. A programmer can change the questions in App
Inventor, thereby creating a new version of the app, but the end-user has
no way to modify the questions or add new questions.
Now suppose you wanted a quiz app that allows one end-user (the teacher)
to change or add new questions. You might envision a parent creating
various quizzes for their child on a long car-trip, or a school teacher setting
up quizzes for students.
Given what we've learned so far, you could write an app that allows the list
of questions to be changed. The user would enter new questions and
answers in text boxes, click Submit, and the event-handler would add new
entries to the list. Such a scheme would work reasonably in the car-trip
scenario-- with the app continually running, the parent (quiz creator) and
child (quiz taker) could pass the phone back and forth.
The scheme is limited, however, because the lists in App Inventor are
transient data: when the app is closed, changes to lists are not recorded.
Any questions entered by the user during a single "run" of the app are lost
when the app is closed, and the next time the app is opened, it will show
only the questions that are fixed part of the list blocks. Furthermore, the
questions entered live only on the particular phone on which they are
entered. So a teacher couldn't write a quiz for her students and allow them
to take the quiz on their own phones.
What our app really needs is access to a database that lives on the web
some place, and that can be accessed by multiple phones.
Persistent data is information stored in a database or a file. It is persistent
in that even when the user closes the app, the data lives on. An example of
persistent data is your profile information on Facebook. When you submit
data to Facebook, the data you submit is stored in a database on the
website's servers. This data is persistent since it will be there the next time
you visit the site or run a Facebook app.
With App Inventor, list variables are not persistent, so the app cannot just
put teacher-submitted questions in a list. Instead, the app must store
submitted the questions in a database. This way, when a student decides to
take a test, even from a different phone, it can access the updated questions
from the datbase. The next section demonstrates how to store to and
retrieve from a database in the App Inventor world.
TinyWebDB
App Inventor provides a component, tinywebdb, which allows for apps to
store and retrieve data from a database. The component can store data on
any web service that follows a particular protocol.
The TinyWebDB component is found in the Not ready for prime time drawer
of the designer. When you drag a TinyWebDB component into your app, it is
placed in the 'non-visual component' area.
The component has one key property: the ServiceURL. By default, the
ServiceURL property is set to http://appinvtinywebdb.appspot.com, which is
a test service set-up by the Google App Inventor team. This test service is
shared by many and has a limit of 100 entries, but it can be used to try
things out.
For production apps, you'll want to set-up a service that you don't share with
other apps. For this sample, we'll use a service set up at the University of
San Francisco: http://usfwebservice.appspot.com:
The TinyWeb DB component is straight-forward to use: you call StoreValue
to store data with a tag and value. You request previously stored data by
calling GetValue and providing a tag. When your phone receives the data
from a request, a GotValue event is triggered.
To illustrate how things work, we'll begin with simplified version of the quiz
app, one with only one question and answer. We'll consider only a "teacher"
app that allows a teacher to view and modify the stored question and
answer. As an exercise, we'll consider a second app that allows a student, on
the same phone or another, to take the single question quiz.
With the teacher app, suppose there are two text boxes, Question Text and
AnswerText, in which the teacher enters the question and answer. When the
teacher clicks submit, the text that has been input in those boxes is stored
to the database using TinyWebDB.
Here are the blocks for the SubmitButton.Click event-handler:
The blocks just call the TinyWebDB.StoreValue function twice, once to store
the question, with a tag of "QuizQuestion", and one to store the answer,
with a tag of "QuizAnswer". The value of each is the text that the user has
input into the respective textbox.
This code doesn't change anything in the phone's display. Instead, its
purpose is to modify the database. If the user enters "Who is the President
of the U.S.?" in the QuestionText box, and "Obama" in the AnswerText box,
the following entries would be put in the database:
tag value
QuizQuestion Who is the President?
QuizAnswer Obama
If the user closes the app, this data remains stored in the database.
The next time the user (teacher) opens the app, the app should display what
was entered previously. To facilitate this, the app calls the GetValue function
in the TinyWebDB.Initialize event:
TinyWebDB.GetValue requests data with a given tag. Here, we make two
requests, one for the question and one for the answer, using the same tags
we used to store the data above.
The GetValue function doesn't get a result directly; it just makes a request
to the TinyWebDB web service. After making the requests, the app is free to
handle other events while the web service is sending the requested data.
When the the requested data arrives at the phone, a GotValue event is
triggered. It in this event-handler that the app can do something with the
data it requested. Here are the blocks for the GotValue event:
Both the requests the app made in the Initialize event will trigger GotValue
events, so the Got-Value event-handler will be invoked twice. Because of
this, the handler must first ask which data is being received. Each entry
received contains both the tag and the value, so the handler can ask if the
tag returned was "QuizQuestion". If it is, the app takes the value ("Who is
the President of the U.S.?") and places it in the QuestionText.Text.
If the tag is not "QuizQuestion", it must be "QuizAnswer", so in the "else-do"
blocks the app places the value ("Obama") in the AnswerText.
A Quiz with Multiple Questions
Now let's extend the simple quiz application so that there are multiple
question and answer pairs. We'll still focus on the teacher app for creating
quizzes.
Here's a simple "teacher" interface for entering test questions:
Previously entered question-answer pairs will appear below the text "Existing
QAs".
The application will put entries into tinyweb db in the following the form:
tag value
WolbQuiz:1 What is the capital of California:Sacramento
WolbQuiz:2 What is the capital of Washington: Olympia
Each tag consists of a keyword to identify this particular application,
"WolbQuiz", along with a number that uniquely identifies the question. Later
in this lesson, we'll discuss how to build the tags using text and join.
The tags must be designed so that they can be reproduced to access the
data in the value field. They shouldn't contain dynamic data-- data that the
user enters-- because our app doesn't know what that data will be. For
instance, you wouldn't want the question to be a tag because the questions
themselves are dynamic data.
The value of each entry in our scheme has both the question and answer,
with a colon separating.
The sample app in this lesson is active. You can check out the actual quiz
questions by visiting the web interface to the tinywebdb service at:
http://usfwebservice.appspot.com. When you get to the page, click on
getvalue and enter a tag such as "WolbQuiz:1".
Programming the Behavior of the "Teacher" Application
Following are the blocks for the teacher app:
On start-up, the app needs to load in the questions from the database so
that the teacher can see the current quiz. The strategy is to request the first
question-answer pair using "WolbQuiz:1". If it returns with a value, the app
requests the second question, and so on, until a request is made that
doesn't not return us a valid value. For example, if there were four questions
stored in the web service, our fifth request ("WolbQuiz:5") will return an
empty value since there is only tags up to "WolbQuiz:4". At that point, the
app knows all questions have been loaded.
The TinyWebDB.Initialize event triggers this process by calling GetValue with
the first key, "WolbQuiz:1". "WolbQuiz:1" is built using a join operation: we
join the text "WolbQuiz:" with the variable qnum.
When the app begins, the variable qnum has an initial value of 1. qnum will
be incremented later so that we can access the successive questions.
Recall that the TinyWebDB.GetValue call just requests the data from the web
service-- the value is not returned to the GetValue block directly. Instead,
when the data arrives to the phone from the web service, a
TinyWebDB.GotValue event is triggered. The blocks in that event-handler
will determine what the app does with the values returned from the
requests:
In the GotValue event, the app first checks to see if the value returned is the
empty string (has length of 0). If so, we know that our last request was for a
tag that doesn't exist in the tinywebdb web service database. This might
happen on our first request if no questions have ever been added, or it will
happen on the nth request if there are n-1 questions in the database.
If the value returned is empty, this means the loading of previously recorded
question-answer pairs is complete, so the app can enable the Submit button
so that the user can enter new entries.
If the value returned does not have a length of 0, the app has received a
valid question-answer pair, and the "else-do" blocks are executed. The first
thing those blocks do is add the question-answer pair returned into
ExistingLabel, which displays all of the question-answer pairs. A join is used
to concatenate the previous value of ExistingLabel with a newline character
("\n") and the new question-answer pair (valueFromWebDB). So if
ExistingLabel was showing:
What is the capital of California:Sacramento
and the newly accessed question was
What is the capital of Washington: Olympia
then the ExistingLabel label would be updated to:
What is the capital of California:Sacramento
What is the capital of Washington: Olympia
with the second question on a separate line due to the "\n".
Besides displaying the entry received from the database, the GotValue
event-handler must also request the next question (we only request the first
in the Initialize event). To do this, it increments qnum and requests the next
question from TinyWebDB.
Processing the Entry of New Question-Answer Pairs
The app also allows the user ("teacher") to enter new question-answer pairs.
The app has two textboxes, QuestionText and AnswerText, and a
SubmitButton. Recall that the GotValue event handler only enables the
SubmitButton when all the question-answers from the database have been
loaded, so the SubmitButton.Click event can only be triggered after that
process is complete. At that point, the variable qnum is set to the number of
questions that were in the database, e.g., 4. Here is the SubmitButton.Click
handler:
The SubmitButton.Click event handler first builds a new question-answer
pair by joining the user's input from QuestionText and AnswerText with a
colon in between. It then builds the tag as was done above with "WolbQuiz:"
joined with qnum, and calls TinyWebDB.StoreValue to store the new data. To
keep the list of question-answer pairs being displayed up-to-date, the
ExistingLabel is updated with the new entry.
Summary
With the TinyWebDB component, you can create apps that remember
things-- that store things in a database. Creating such an app requires you
to design how the data will be stored using the restricted key-value pairs
that TinyWebDB allows. You'll need a schemes such as was used in the quiz
app-- a list of items separated by ";;" with each field in the item separated
by "::". Then you'll need to program the blocks so that the data is inserted
and retrieved in that manner. Fortunately, the Text operations like join and
split make this relatively easy.
Problems
1. Create an application that stores your vote-- whatever you enter in a
textbox-- in the usfwebservice with a tag of your first name. The application
should also show you what you have previously entered (as in the sample).
2. Working with a partner or partners, have your app show the votes of
three or more people.
3. Write a quiz creator (teacher app) as described in this sample.
4. Write a quiz taker app. that lets the user take the quiz stored in the
database.