Browsing and using websites
Back in the day, when I first started writing, there were two ways to research—own a lot of books (I did and still do), and/or spend a lot of time at the library (I did, don't have to now).
This all changed in the early 90s when Sir Tim Berners-Lee invented the World Wide Web (WWW) . The web used the Internet, which was already there, although Al Gore did not invent the Internet. Although earlier experiments took place, Vinton Cerf's development of the basic transmission protocols making all we enjoy today possible gives him the title "Father of the Internet".
All of us reading this book use the Internet and the web almost every day. App Inventor itself relies extensively on the web; you have to use the web in designing apps and downloading the Blocks Editor to power them up.
Adding web browsing to our apps gives us:
- Access to literally trillions of web pages (no one knows how many; Google said it was over a trillion in 2008, and growth has been tremendous since then).
- Lets us leverage the limited resources and storage capacity of the user's phone by many times as we use the millions of dollars invested in server farms (vast collections of interconnected computers) and thousands of web pages on commercial sites (which they want us to use, even beg us to use because it promotes their products or services).
- Makes it possible to write powerful and useful apps with really little effort on our part.
Take, for example, what I referred to earlier in this book as a link app. This is an app that, when called by the user, simply uses ActivityStarter to open a browser and load a web page.
Let's whip one up.
Time for action – building an eBay link app
Yes, eBay loves us—especially if we buy or sell items on this extensive online auction site. And they want you to do it not just at home but when you're out with only your smartphone.
To encourage use from your phone, eBay has spent a gazillion dollars (that's a lot) in providing a mobile site (http://m.ebay.com) that makes the entire eBay site (hundreds of thousands, probably millions of pages) available and useful to you.
Back to that word, leverage—the ancient Greek mathematician, Archimedes, said about levers, "Give me a place to stand on and I will move the Earth." Our app's leverage won't move the Earth, but we can sure bid on just about everything on it.
Okay, the design of our eBay app is very simple since the screen will be there for only a second or so. I'll explain that in a moment.
So, we need just a label and two non-visual components: ActivityStarter and Clock. In the Properties column for the ActivityStarter, put android.intent.action.VIEW in the Action field (again, this is how your app calls the phone's web browser, and the way it's entered is case-sensitive).
This gives us something as shown in the following screenshot (with a little formatting added):
Now, the reason for the LOADING...\nInternet connection required (in the label, \n being a line break) is a basic notifier and error trap. First, if the Internet connection is slow, it lets the user know something is happening. Second, if there is not 3G or Wi-Fi connection, it tells the user why nothing will happen until they get a connection.
Simple additions like the previous (basically thinking of the user's experience in using our apps) define the difference between amateur and professional apps.
Always try to anticipate, because if we leave any way possible at all to screw it up, some user will find it. And who gets blamed? Right. You, me, or whatever idiot wrote that defective app. And they will zing you on Android Market.
Okay, now to our buddy: the Blocks Editor.
We need only one small block group. Everything is in the Clock1.Timer block to connect to the eBay mobile site and then, job done, gracefully exit.
Inside the clock timer frame, we put four blocks, which accomplish the following logic:
- In our ActivityStarter1.DataUri goes the web address of the eBay mobile website home: http://m.ebay.com.
- The ActivityStarter1.StartActivity block calls the phone's web browser and passes the address to it.
- Clock1.TimerAlwaysFires set to false tells AI, "Stop, don't do anything else."
- Finally, the close application block (which we should always be nice and include somewhere in our apps) removes the app from the phone or other Android device's memory, releasing those always scarce resources.
Make a nice icon, and it's ready to go onto Android Market (I put mine on as eBay for Droids).
What just happened?
That's it—a complete application giving access to a few million great bargains on eBay.
This is how it will look when the eBay mobile site home page opens on the user's phone:
Pretty neat, huh? And there are lots of other major sites out there that offer mobile sites, easily converted into link apps such as this eBay example.
But, what if you want to make the app more complex with a lot of choices? One that after the user finishes browsing a site, they come back to your app and choose yet another site to visit? No problem.
Here's an example of that. I recently published an app called AVLnews (AVL is the airport code for Asheville, North Carolina where I live). This app actually lets the user drill down into local news for all 19 counties in the Western North Carolina mountains. Here's what the front page of the app looks like:
Even with several pages of choices, this type of app is truly easy to create. You need only a few buttons, labels, and (as ever) horizontal and vertical arrangements for formatting. And, of course, add a single ActivityStarter for calling the phone's web browser.
Now, here's the cool part! No matter how long and how many pages your user reads on the site a button sends him to, when he or she hits the hardware Back button on their phone, they return to your app.
The preceding is the only way the Back button works for an App Inventor app! If user is within an AI app and hits the Back button, it immediately kills your app (except when a listpicker is displayed, in which case it returns you to the screen that invoked it). This is doubleplusungood, so to speak. So, always supply navigation buttons for changing pages and maybe a note somewhere not to use the hardware button.
Okay, back to my AVLnews app as an example. The first button I built was for the Citizen-Times, our major newspaper in the area. They have a mobile site such as the one we saw earlier for eBay. It looks nice and is easy to read on a Droid or other smartphone, like the following:
And, it's equally easy to program—this is all you need:
I then moved on to other news sources for the areas. The small weekly newspapers in the more isolated, outlying mountain counties have no expensive mobile sites. The websites they do have are pretty conventional.
But, when I linked to them, the page would come up with tiny, unreadable type. I had to move it around, do the double tap on the content to fit to the page trick to expand the page, turn the phone on its side, and many such more, and still had trouble reading stuff.
Folks, you do not do things like that to your users. Not if you want them to think you are one cool app inventor, as I know you to be by now.
So, here's the trick to making almost all web pages readable on a phone—Google Mobilizer! It's a free service of Google at http://www.google.com/gwt/n. Use it to construct links that return a nicely formatted and readable page as shown in the next screenshot. People will thank you for it and think you expended many hours of genius-level programming effort to achieve it. And, remember, it's not polite to disagree with people, eh?
Often, the search terms and mobilizing of your link is long and goes on for some time (the following screenshot is only a part of it). However, that's where your real genius comes into play: building a search term that gets the articles fitting whatever is the topic on the button.
Summing up: using the power of the web lets us build powerful apps that use few resources on the phone yet return thousands upon thousands of pages. Enjoy.
Now, we will look at yet another Google service: Fusion Tables. And see how our App Inventor apps can take advantage of these online data sources.
Fusion Tables—Google's free online data service
Google Fusion Tables is a free online service for managing large collections of tabular data (data in tables). If you have a Google account (and you do or you couldn't be using App Inventor), you can upload tables of up to 100 MB and share them with people you choose, or make them public.
You can also import and export Fusion Table data as CSV (comma-separated values).
There are numerous public tables that you can pull data from, such as the following example of coffee imports by country from the International Coffee Organization. I certainly depend on high levels of world coffee production in writing my books.
Having three methods, especially when their functionality overlap somewhat, might be a little confusing. But, again, it's still early days in the development of App Inventor.
Here's my prediction. I think—as the Web component becomes more powerful, especially after headers are fixed so that the Post method can be used easily—TinyWebDB (a bit complicated as it is) will eventually fade away. The FusiontablesControl component will be further developed and stay around because it's specific to that particular service.
Which of these three methods do you use, and for what?
Web and TinyWebDB are better (more flexible, more powerful) if you have access to database frontend (or the ability and permissions needed to program them) on a wide range of web servers.
A second advantage of the previous two ways is the ability to conveniently control data access. If you write apps where online data is provided, for example, you can securely specify what searches are allowed, what, if any, SQL (structured query language) input is accepted and acted on, and so forth. This is typically achieved through a PHP or Python frontend script.
However, certainly the greater majority of App Inventors (we who use App Inventor) will not have extensive access to online servers. In that case, Google Tables is not a bad alternative.
The disadvantages of Google Tables are the limitation in size (yeah, 100 MB may sound like a lot, but databases get big) and the difficulty in sharing access to the data.
This latter disadvantage is irksome. Google Tables requires the user to be logged in to their Google account to use even the public tables. In writing an app that needs access to online data, you cannot (and should not) depend on your users to all be logged in, especially from a phone.
Anyway, there are apps for your own use that Google Tables will be good for and—since the GoogletablesControl component is still under development, we can always hope for a solution to the data sharing drawback (please, guys?).
Earlier I shared with you the mileage log app I'm writing for one of my companies where we need to track travel distance. The following is the design portion of the app:
Constructing a display of table data requires a bit of tedious formatting in order to get a neat looking result as follows. I used labels with a white background and two pixels thick to make all the lines.
For the FusiontableControl component to get data, it has to know which database to query. Luckily, it already knows where Fusion Tables is in general. We get the database number by looking at the dsrcid variable in the URL of the database in our browser. The dscrid is used to reference a Fusion Table; sort of like an IP address translating to a name. In the case of the Coffee Import by Country public table, it is 94782.
Let's just pull out countries. Go to Google Tables, and look under the public tables for the previous one; it's reasonably close to the top.
So, we make an SQL query using rules and examples in the help material about Fusion Tables online and come up with select 'Importing Country' from 94782. We enter this information in the Query field that appears in the Properties column of Design when the FusiontablesControl component is in place and selected.
In Blocks Editor, we put the FusiontablesControl1.DoQuery in the button block (as shown in the next screenshot), which fires off the request when the button is tapped (asking us to log in, of course). And, in the FusiontablesControl1.GotResult, we put the value of the result (that block is in My Definitions) into a label so we can see it.
And get a list of countries as follows:
We can also use the FusionTablesControl1.Query block to let the app control the query to Fusion Tables rather than putting just one into the Query field in the Properties column of Design. This is shown in the next screenshot.
Also shown on the left is the entire drawer created in My Blocks when you drop a FusiontablesControl component onto the virtual screen in Design. Not much to it, which tells us why this component still lives in the Not ready for prime time drawer in Design.
But, this does not mean FusiontablesControl is not yet useful. It is. Just so long as we understand the parameters of using Fusion Tables, which include:
- It's moderately simple, more like a spreadsheet than a powerful relational database such as MySQL, my favorite PostgreSQL, or the commercial powerhouse of Oracle.
- The search terms are also limited compared to what you can do with the databases listed previously.
- Despite being able to share your private tables or even make them public, the user is still required to have a Google account to access them; currently a killer so far as using Fusion Tables in widely disseminated apps to the general public, many of whom will not have such an account.
Teaching you how Fusion Tables works is beyond the scope and space available here, but a good starting point in learning how search terms work is: http://code.google.com/apis/fusiontables/docs/developers_guide.html.
However, I can (and certainly should) show you what to do with CSV tables imported into App Inventor. This technique works not just with Fusion Tables but with imports from pretty much any online database.
One thing you'll need to know is (as I mentioned several times) the structure of the table you're working with. If you created the table on Fusion Tables, you know its structure. If you want to use one of the public tables, either just take a look at it online or we can use AI to find out for us as shown in the following screenshot by using describe <number of table> as the query:
Which, in the case of 94782 (the coffee import table), returns the structure of the table, providing us with a reference to display the CSV table when we import it:
Well, that was easy enough. In the example earlier, we had simple data coming back from our query; that is, not a list, but just a single term (the list of countries) with a handy line return at the end of each one. No formatting was needed in displaying it in a label as previously.
Most usable data from an online database of any sort, not just Fusion Tables, will be in CSV table form—fields separated by commas, making up records separated by line returns.
We convert the CSV table returned from a query to my Fusion Tables table into lists and those lists into columns and rows for displaying.
The query (search) term I used was select * from 742086, which tells Fusion Tables to send us everything in table 742086—which is a private table of mine.
Displaying a table on the phone is not complicated, but it is a bit tedious. Here's a portion of the way I do it in the Mileage app:
The steps are simple enough:
- When the button is tapped, get the table from Fusion Tables (I also get the table when the app initializes so that the table is populated from the first).
- Convert value result (the table) into the global variable mileage. We now have a list of lists where each of the sublists are records (rows) of the table.
- For each row, select each field and display it. In my case, we have three vehicles for which I want the name of the vehicle, starting mileage, ending mileage, type of trip, date, and current total miles traveled.
To get the correct number of rows (records) and columns (fields), you have to know the structure of the database you're importing. That is critical. Since I created this table in Fusion Tables, I know its structure and, in Design (see the next screenshot), can set up a display table with a row of headings (column names), and three rows (one for each vehicle).
I use labels with white backgrounds and two pixels wide as dividers and labels—these latter named as row3_6 and row4_5 to show me which row and column they are in. Believe me, in something this (I'll use the word again) tedious, naming your labels is crucial in avoiding confusion.
Tapping the Get Mileage Log button imports the table, converts it from CSV to a list of lists, and breaks out the data as shown in the following screenshot. The names of the vehicle (actual names of our three Kias) go in the first column, and the other columns are filled appropriately as to type of trip. Among several businesses we run is a notary signing service doing real estate refinance closings, and that's what generates most trips (see http://portablenotary.com). And do check to make sure the app's arithmetic is correct—35000 - 30000 should be 5000! I need to revisit that app.
How do we get data back up to Fusion Tables? Well, in the actual production version of Mileage (when I get time to finish writing it), we'll tap on the name of the vehicle (that label will be turned into a button), and a screen comes up showing the last three trips (just for reference) and asking for the new ending mileage and the type of trip.
From that, starting and stopping miles are revised by the app, the type of trip noted, the current date added, and the number of miles for the trip calculated. So, we wind up with a new record (row) of data like this (it can be a list):
(Target 69000 69014 Personal 7/11/11 14)
Now, we want to add this new trip for Target (he's my personal chariot) to the table up on Fusion Tables, wherever it be out there in the cloud. The user (me, in this case) simply taps the Save button.
Oh, yeah, we better tell that Save button how to save. Just to make this faster, I'm going to manually build the query that goes back up (in production, I'll be pulling it out of a list variable to make this same query string). Here's what it looks like:
And, when we check online, we find (last row) it saved the row of data by adding it to the rows (records) that were already there.
That's a basic introduction to Google Fusion Tables and the FusiontableControl component.
To sum up, Fusion Tables are a limited but useful way of storing and retrieving data online in spreadsheet-like tables. They have the disadvantage of requiring the user to have a Google account.
And, one more disadvantage: Google Tables are still in beta testing (as is App Inventor itself). Google Tables are slow.
Since Google Tables are slow, you'll want to limit reads and writes as much as possible.
It is now time for us to take a look at TinyWebDB—which is the third method of using online databases from App Inventor apps. ... Oops! Wait! I just thought of another way.
Quickie data-getter—finding the fourth way
Okay, here's a bonus, guys. Here, I'm reminded of the old story about the scientists who put a monkey in a room with only three ways out. The monkey finds a fourth way.
A fourth way of accessing online databases (those that allow Get queries) is a simple ActivityStarter activated by a button.
Which gives us this on the phone:
Yes, we did essentially this same thing in the eBay link app example, but we were just calling the mobile website there. Previously, we actually passed a query (via Get) to the server and can pull specific replies from the database.
The advantage to this quickie technique is you don't have to parse the result; it shows up with formatting, images, and so on. For example, I have almost 200 videos on YouTube. What if I wanted a neatly formatted app to help people with Android devices find and watch them easily?
No problem. Just find the right search term on YouTube, and set up my link app as so:
And we get nicely formatted lists of my videos with hardly any work! The previous close application block removes the app from memory, once its job of bringing up the video list is complete.
In this article, we learned how to browse and leverage the power of websites and the use of Fusion Tables (Google's free online data service).
- Google Web Toolkit GWT Java AJAX Programming [Article]
- Google SketchUp for Game Design: Beginner's Guide [Article]
- Google Earth, Google Maps and Your Photos: a Tutorial [Article]
- Google Apps: Mastering Integration and Customization [Article]