Using SPARQL queries from native Android apps

With a free, kid-friendly development kit.

App Inventor and RDF logos

Google once developed a simple environment called Google App Inventor for easy development of native Android apps. After they announced that they would discontinue support and open source it in 2011, the MIT Center for Mobile learning picked it up, so it’s now the MIT App Inventor. (Its Wikipedia page has a nice summary of its history.) I played with it a bit and found it pretty easy to build apps for my phone, even an app that used an RDFS model to drive a user interface. My simple experiments only scratched the surface of what was possible using SPARQL and RDF as part of a mobile app, and much more sophisticated work is on the way from our friends at the Tetherless World Constellation group.

To get a flavor for how application development works with this toolkit, flip through some of the tutorials, especially the Hello Purr one where they recommend that you start. After installing an App Inventor tool on your phone, you log in with a Google ID to a web-based application that lets you design your screens by dragging on and configuring various components. From there, you download a Java application called the blocks editor where you configure programming logic. With a wi-fi connection from the machine running those to your phone, you can try out your app on your phone as you work on it with the screen designer and blocks editor. The documentation tells you more about the available components and blocks.

The screen designer lets you add pick lists to your app, and because their choices can be configured dynamically (and because an App Inventor web component lets you do HTTP GETs, and because there are plenty of string manipulation functions) I wrote an app that sets the pick list choices with the results of a SPARQL query. It’s a nice example of model-driven development—something we talk about a lot at TopQuadrant—in which an application’s behavior is driven by a model stored in an RDFS schema or an OWL ontology.

I’ve written more about how my little phone app works below, but first wanted to say a little more about the Tetherless World Constellation’s work on new App Inventor semantic web components for use in these applications, because these will allow much more sophisticated use of RDF than my demo does. Others at MIT have already built a Disaster relief phone app with it.

Instead of logging in to the web-based screen design app mentioned above, using these new semantic web components currently requires the use of a specialized version of this application hosted at tw.rpi.edu. Apparently these new components are on their way to inclusion in App Inventor 2, so I’m really looking forward to that. You can learn more about how these extensions work from a YouTube video of a presentation by Tetherless World’s Evan Patton titled Extending the MIT AppInventor with Semantic Web Techno.

My little application lets you pick an item of clothing, the size, and the color, and then it sends a string of the selected data off to a script on another server.

The choice of items, sizes, and colors comes from the model below, stored on a SPARQL endpoint:

@prefix ps:   <http://snee.com/ns/demos/productSchema#> . 
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . 

ps:Product a rdfs:Class . 

ps:Color   a rdfs:Class . 

ps:Size    a rdfs:Class . 

ps:color a rdf:Property ;
         rdfs:domain ps:Product ;
         rdfs:range ps:Color .

ps:size a rdf:Property ;
        rdfs:domain ps:Product ;
        rdfs:range ps:Size .

ps:tshirt  a ps:Product ; rdfs:label "T-shirt" . 
ps:sweater a ps:Product ; rdfs:label "sweater" . 
ps:pants   a ps:Product ; rdfs:label "pants" . 

ps:black a ps:Color ; rdfs:label "black" . 
ps:blue  a ps:Color ; rdfs:label "blue" . 
ps:white a ps:Color ; rdfs:label "white" . 

ps:small  a ps:Size ; rdfs:label "small" . 
ps:medium a ps:Size ; rdfs:label "medium" . 
ps:large  a ps:Size ; rdfs:label "large" . 

When you touch the color button on the interface, the app displays the choices from the model:

Selecting one displays that value on the button:

After you select an item, color, and size, touching the Submit button sends the selected data off to another web server with an HTTP GET.

The interesting part of this app (at least, to RDF geeks) is clearer when we change the model that specifies the interface details—for example, by adding a new instance to the data model’s Color class on the server with the SPARQL endpoint:

ps:red a ps:Color ; rdfs:label "red" . 

After clicking the app’s Refresh button (or shutting down and restarting the app) the next time you press the Select Color button, you’ll see the new choice of colors reflected:

Here’s how it works: upon startup or when pressing the Refresh button, the app sends the following query to the SPARQL endpoint to find out how instances of the Product class are modeled, requesting the result as comma-separated values. To do this, the query asks for all the properties associated with the Product class (that is, which properties have an rdfs:domain of ps:Product) and what their potential values are (that is, what the instances of the class specified as each property’s rdfs:range value are):

PREFIX ps:   <http://snee.com/ns/demos/productSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 

SELECT ?list ?listItem
WHERE 
{
  {
    ?property rdfs:domain ps:Product ;
              rdfs:range ?range . 
    ?propertyValue a ?range ;
                   rdfs:label ?listItem .
    BIND(strafter(str(?property),"#") AS ?list)
  }
  UNION
  { 
    ?item a ps:Product ; rdfs:label ?listItem .
    BIND("item" AS ?list)
  }
}

App Inventor blocks offer plenty of options for parsing out the CSV, so my app uses some of these to find the values it needs in the query result and then uses those values to set each list picker widget’s choices.

If the data had included the value labels in multiple languages, like this, the query above would need a small addition to retrieve only the English versions of the labels:

ps:black a ps:Color ; rdfs:label "black"@en ; rdfs:label "negro"@es . 
ps:blue  a ps:Color ; rdfs:label "blue"@en  ; rdfs:label "azul"@es .  
ps:white a ps:Color ; rdfs:label "white"@en ; rdfs:label "blanco"@es .  

A slight change to that version of the query could have it retrieve the Spanish labels instead, so creating an Android app with easily configurable multi-language support would be easy. (I could use the same technique of using RDF and SPARQL to change the rest of the text on the form—for example, to change the button label “Select Size” to say “Selecciona Tamaño.”) Because App Inventor lets you dynamically assemble the URL containing the SPARQL query before sending it to the endpoint, the app could modify the query to retrieve either English or Spanish labels based on whether the user picked “English” or “español” from a new “Select language” button that would be easy to add.

It would have been even nicer if, instead of hardcoding my form with Item, Color, and Size fields, those could have been auto-generated in the form based on which properties the query found that had an rdfs:domain value of ps:Product. This is the sort of thing that the Tetherless World extension will allow. (TopQuadrant’s TopBraid platform has always made this possible, but native phone apps are not a current target.)

I want to reiterate two key points about App Inventor: first, it’s very easy to use, drawing a lot on MIT research into programming for kids using environments such as Scratch. (Young people continue to be a big target for App Inventor developer evangelism.) Second—and this is especially impressive considering that we’re talking about a programming environment that’s so easy to use—it’s creating native apps. You’re not creating scripts that require some runtime thing to execute; you can create .apk files that anyone with an Android phone can install and use. I think that this is pretty exciting, and the ability to work RDF-based technology into the mix makes it even more exciting.