Skip to content

Welcome!

Search the categories on the right for examples.

If you can't find what you need, then leave a comment on the Requests page!

Happy coding everyone.

New Add me on Twitter to get tweets on Think Android's latest posts!

Merry Christmas and Happy Birthday

December 25, 2011

Two years ago today, still a junior in college and bored out of my mind at home, I started this blog with a humble post.

My goal for this blog was simple: I wanted to share not just my coding experiences, and little tips and tricks I picked up along the way, but I wanted to share my code – and tons of it. I’m a firm believer that sometimes, the most helpful way to learn how to master a platform/language is just by looking at tons of code.

And now, 800,000 views and 40 tutorials later, I hope I was able to accomplish that to some extent. What do you guys think?

This blog has been a joy to keep up with and even though I’m starting to run out of tutorial ideas, I hope you guys continue to find great use out of it.

Until next time, happy coding, and:

StringBuilder sb = new StringBuilder();
sb.append("MERRY CHRISTMAS!");
sb.append("AND");
sb.append("HAPPY BIRTHDAY THINK ANDROID!");

System.out.println(sb.toString());

- jwei

Google App Engine – Final Thoughts and Comments

December 18, 2011

Hey everyone,

So now that I’ve officially finished my Google App Engine series (which I hope you will all find useful and applicable), I just wanted to share some final thoughts I had on application development, and provide a little motivation for why I decided to move away from a purely-Android-focused blog.

My school of thought for software engineering goes along the lines with this (in my opinion) spot on Techcrunch post:

http://techcrunch.com/2011/05/07/why-the-new-guy-cant-code/

In it, the author talks about how “a great coder can easily be 50 times more productive than a mediocre one, while bad ones ultimately have negative productivity” and I think this is a sentiment that’s shared across many recruiters and start-up founders in the bay. So now the question is, what does it take to be a great software engineer, and for recruiters, how do you find these great software engineers?

For those of you who have interviewed with tech companies you’ll know that the typical tech interview consists of maybe one or two brain teasers followed by a slew of algorithm-based questions (how do you reverse a string? what’s the run time? etc) and random one-liner language-specific based questions. However, is this really the best way to pick out a great programmer?

I would argue no.

“So what should a real interview consist of? Let me offer a humble proposal: don’t interview anyone who hasn’t accomplished anything. Ever. Certificates and degrees are not accomplishments; I mean real-world projects with real-world users. There is no excuse for software developers who don’t have a site, app, or service they can point to and say, “I did this, all by myself!” in a world where Google App Engine and Amazon Web Services have free service tiers, and it costs all of $25 to register as an Android developer and publish an app on the Android Market.”

Sure, every competent programmer should have a strong understanding of algorithms, run-time complexities, data structures, etc. But more importantly, every great programmer should be a great problem solver.

Sometimes this might mean knowing what the most efficient algorithm is, or what the most natural data structure is. But many other times, this may mean knowing what the best platform is for your back end or front end: being able to think ahead, and see the application from a macro-perspective. Many times this may mean knowing when the best solution is an ad-hoc solution, and when the best solution is a well-thought out, efficient solution: when it’s okay to ignore the ugly double for loop and push on for the sake of application as a whole.

At the end of the day, a great programmer is a great problem solver – and problem solving isn’t limited to algorithms.

And so I encourage you all to leverage the plethora of tools available to you today and build, build, build! Build until you can see and think about an application, not just as a back-end engineer, or a front-end engineer, or even a product manager, but as someone who can traverse the roles and see the entire application from above: where it is right now and where it needs to be 1 week from now, 1 month from now, 1 year from now.

Think like a problem solver, and love the journey along the way.

Until next time, happy coding and happy holidays.

- jwei

Google App Engine – Bringing it Back To Android (4)

December 18, 2011

Hey everyone,

And so we come to the end of our series and we bring it all together and bring it back to Android.

At this point, we have a fully functional, scalable GAE back-end, equipped with cron-jobs that insure your database has the most up to date data, and with servlets put in place so that any platform can make an HTTP request and get your data. All that remains is how to make these HTTP requests from Android, and how to bind this data to the UI once it’s been retrieved.

It’s really very simple and a number of my tutorials in the past have touched on this topic. To start you’ll need to build an HTTP Client which will allow you to make GET/POST requests. The code for this can be found here and in my case I put this code into a class called ConnectionManager. Once you have that, I prefer to build some simple GET/POST wrapper methods, and the code for those look like:

public class GetMethods {

    private static final String LOG_TAG = "GetMethods";

    // THIS IS THE GET METHOD YOU WILL BE CALLING
    // HERE YOU JUST NEED TO PASS IN:
    // 1) THE URL YOU WANT TO MAKE THE REQUEST TO
    // 2) THE HTTP CLIENT YOU INITIATED (FROM ABOVE)
    public static String doGetWithResponse(String mUrl, DefaultHttpClient httpClient) {
        String ret = null;
        HttpResponse response = null;

        HttpGet getMethod = new HttpGet(mUrl);
        try {
            response = httpClient.execute(getMethod);
            Log.i(LOG_TAG, "STATUS CODE: " + String.valueOf(response.getStatusLine().getStatusCode()));
            if (null != response) {
                // helper method to convert HTTP response to String
                ret = getResponseBody(response);
            }
        } catch (Exception e) {
            Log.e("Exception", e.getMessage());
        } finally {
        }
        return ret;
    }

    public static String getResponseBody(HttpResponse response) {
        String response_text = null;
        HttpEntity entity = null;

        try {
            entity = response.getEntity();
            response_text = _getResponseBody(entity);
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            if (entity != null) {
                try {
                    entity.consumeContent();
                } catch (IOException e1) {
                     // error
                }
            }
        }
        return response_text;
    }

For POST requests, code is pretty similar and I talk about those here. Now that we have these nifty generalized GET/POST requests, the rest is super simple. Here’s how to make a GET request for the video games shown in the previous post:

import java.util.List;

import org.apache.http.impl.client.DefaultHttpClient;

import com.juicy.app.objects.Constants;
import com.juicy.app.objects.VideoGame;
import com.juicy.app.service.ObjectParsers;

public class GetVideoGames {

    private static String URL_BASE = "http://entertainmentapp.appspot.com"

    private static String REQUEST_BASE = "/getVideoGames?type="

    // THIS RETRIEVES THE HTTP CLIENT CONFIGURED ABOVE
    private static DefaultHttpClient httpClient = ConnectionManager.getClient();

    // HERE YOU PASS IN THE PLATFORM YOU WANT I.E. XBOX, PS3, ETC
    public static List<VideoGame> getGamesByPlatform(String platform) {
        // construct the URL
        String url = URL_BASE + REQUEST_BASE + platform;

        // get the XML response back as a String
        String response = GetMethods.doGetWithResponse(url, httpClient);

        // create a simple String parser
        // here we want to convert XML to a list of VideoGame objects
        List<VideoGame> games = ObjectParsers.parseGameResponse(response);
        return games;
    }

}

Again, just to reiterate, here we’re simply constructing the correct URL with the specified platform in this case, and then sending it to our new GetMethod wrapper. This GetMethod wrapper will make the GET request and convert the returning HTTP Response object into a more manageable String object. If you want to see what the String looks like, just check out this and pretend like it’s not nicely formatted (i.e. it’s all going to come as one line of characters).

As to how you want to parse that text – this part is really up to you guys (and shouldn’t be too complicated of a task… I’d imagine that if you’re reading this you should have a strong enough grasp of programming to write a String parser). For XML parsing, you can use anything from simple REGEX to more complicated tools like SAX Parsers and XPath (though this might be a little overkill).

If you decide to, instead, return responses in JSON format, then you should definitely use something like JSON in Java which comes with a bunch of nice wrapper methods to help you quickly parse out the fields of each VideoGame object.

Again, just for the sake of completeness though, I’ll show you what I did:

public class ObjectParsers {

    // ad hoc REGEX solution to parsing XML response
    public static List<VideoGame> parseGameResponse(String response) {
        List<VideoGame> games = new ArrayList<VideoGame>();
        String insideContents = RegexParser.regex("<games>(.*)</games>", response);
        String[] contents = insideContents.split("<game>");
        for (String content : contents) {
            if (content.equals("")) {
                continue;
            }
            String name = RegexParser.regex(">([^>]*)</name>", content);
            String id = RegexParser.regex(">([^>]*)</id>", content);
            String imgUrl = RegexParser.regex(">([^>]*)</imgUrl>", content);
            String type = RegexParser.regex(">([^>]*)</type>", content);
            VideoGame v = new VideoGame(Long.parseLong(id), name, imgUrl, type);
            games.add(v);
        }
        return games;
    }

And so now that we’ve 1) made the HTTP request, 2) gotten back the request as an HTTP Response object, 3) converted that response object into a String, and 4) parsed the String and converted it into a List of VideoGame objects, all that we need to do is bind these objects to a UI!

Again, this is a topic that I’ve already covered in a previous tutorial, so I won’t make this tutorial unnecessarily long and verbose and instead will ask you to just look at this post. In my previous post, I use a BaseAdapter to create a list which shows a bunch of Contact objects – here we simply need to modify the code a little so that instead of showing a list of Contact objects we’re showing a list of VideoGame objects.

You’ll also notice that one of the fields returned is “imgUrl”, and so one nice thing I do in my application is that alongside the name of the game I show the user a preview image (also taken from Blockbuster). If you want to learn how to convert a URL to an Bitmap then check out this previous post.

As for how you can load a series of images in a list format quickly and without interrupting the user’s application experience (i.e. blocking the UI thread) this is something I’ll leave you guys to think about (as it’s something I have to think about and improve upon constantly!).

Final Result - Simple Activity displaying video game name and image preview.

And that’s it!

Hope you guys enjoyed this series – I’ll follow up shortly with why I feel so passionately about sharing these kinds of full-on application design experiences with everyone.

Happy Coding.

- jwei

Google App Engine – HTTP Requests (3)

November 27, 2011

Hey everyone,

Hope everyone is sufficiently stuffed from the holidays… I know I am.

But yes to recap, so far we’ve in this series we’ve seen how you can use Google App Engine to set up a back end for your Android application, which includes writing all the wrapper functions for inserting/updating/removing data from the JDO database back end. Then, we looked at powerful automated methods for retrieving data – incredibly important for people who need a strong initial data set in their application before going live with it. And lastly we tied the two together by showing you how to go and retrieve the data and then batch insert it into your JDO database.

And so, at this point, everyone should be able to go to their Google App Engine dashboard and see the following:

VideoGame Database from GAE

As well as a list of your active CRON jobs:

List of active CRON jobs on GAE

Now, moving on. At this point we need to set up our HTTP GET/POST requests – namely we need to be able to call a URL which hits your Google App Engine server and performs some kind of function (typically this will be retrieving some data based on the parameters you pass into the URL, and then returning it in one of two formats – either XML or JSON). This is done through defining an HTTP Servlet and the code is actually quite simple:

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import app.db.VideoGameJDOWrapper;
import app.services.GamesToXMLConverter;
import app.types.VideoGame;

public class GetVideoGames extends HttpServlet {

    private static final long serialVersionUID = 1L;

    // note this is a simple HTTP GET request
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        // from the URL request, retrieve the parameter with name 'type'
        String platform = request.getParameter("type");

        // pass this into our JDO wrapper which then goes and retrieves the games with specified platform type
        List<VideoGame> games = VideoGameJDOWrapper.getGamesByPlatform(platform);

        // convert the list of VideoGame objects into a String with XML format (can be JSON as well)
        String ret = GamesToXMLConverter.convertGamesToXML(games);

        // set the response type to be XML
        response.setContentType("text/xml");
        response.setHeader("Cache-Control", "no-cache");

        // this is the response that you write back to the user
        response.getWriter().write(ret);
    }

}

The GamesToXMLConverter class is also just a wrapper class that given a list of VideoGame objects, will strip out the fields of each and translate them into an XML string. Again, pretty simple code, and I’m sure someone out there has a much cleaner way of doing this object to XML conversion… but this has always worked fine for me:

public class GamesToXMLConverter {

    public static String convertGameToXml(VideoGame g) {
        String content = "";
        content += addTag("name", g.getName().replaceAll("&", "and"));
        content += addTag("id", String.valueOf(g.getId()));
        if (g.getImgUrl() != null) {
            content += addTag("imgUrl", g.getImgUrl().getValue());
        }
        content += addTag("type", VideoGameConsole.convertIntToString(g.getConsoleType()));
        String ret = addTag("game", content);
        return ret;
    }

    public static String convertGamesToXML(List<VideoGame> games) {
        String content = "";
        for (VideoGame g : games) {
            content += convertGameToXml(g);
        }
        String ret = addTag("games",content);
        return ret;
    }

    public static String addTag(String tag, String value) {
        return ("<" + tag + ">" + value + "</" + tag + ">");
    }

}

The last step in this process is simply defining this HTTP servlet in our Google App Engine project. This happens in the project’s /war/WEB-INF/web.xml file, at which point you’ll insert the following code snippet into that file:

<?xml version="1.0" encoding="utf-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">

    <servlet>
        <servlet-name>getVideoGames</servlet-name>
        <servlet-class>app.requests.GetVideoGames</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getVideoGames</servlet-name>
        <url-pattern>/getVideoGames</url-pattern>
    </servlet-mapping>

</web-app>

Note that you must pass in the path to your HTTP Servlet class within the “servlet-class” tags (in my case this was in the app.requests package of my project). The URL pattern will simply tell you the URL path that you need to send your HTTP request to and will look something like:

http://{your-project-name}.appspot.com/getVideoGames?type={type}

And so for me, it looks like:

Sample HTTP GET request for getting Video Games

Feel free to hit the following URLs yourself to get a better idea of what’s going on:

Xbox Request

PS3 Request

Wii Request

And for those that are wondering, by using a browser like Chrome or Firefox (not sure if IE does this) the XML should automatically get formatted nicely (as shown in my sample image).

Any who, that’s it for now! Next step is fairly simple – we now have our HTTP request set up, so all we have to do is hit it from our Android client to retrieve a nicely XML-formatted string of data, at which point we can parse it, cache it, bind it to the UI, etc.

Hope this was helpful – happy holidays and like always, happy coding.

- jwei

Google App Engine – Getting Data (2)

November 20, 2011

Hey everyone!

Onwards we go with Part II of the series! From my first post we now know how to build your own Google App Engine back-end and write a slew of wrappers that allow you to quickly insert/update/remove data. Now, it’s a question of how you get that data.

Sure for some databases (like databases for users and account information) you won’t need to do any initial populating and it’ll naturally build itself in time. But, often times this isn’t the case and you’ll need to present the new user with some initial data set for them to explore – with the hope of converting them into a regular user and potentially giving you back data (but this is an entirely different topic that I’m also quite passionate about… the concept of social data applications).

Examples of this might be if you’re building a new “food spotting” application or a location-based application, or in my case a video game searching application.

As far as the actual scraping of the data goes, I’ve already developed a couple of tutorials related to the subject and so I won’t go too much into it (see Scraping Data) but since this is an examples driven site, I’ll share my code anyways (and let you guys piece everything together):

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

import app.helpers.HTMLNavigator;
import app.types.VideoGame;

public class VideoGameScraper {

    private static String content;

    private static String TITLE_EXPR = "//div[@class='%s']/a[1]";

    private static String IMG_EXPR = "//div[@class='%s']/a[1]/img";

    public static final String BASE_URL = "http://www.blockbuster.com/games/platforms/gamePlatform";

    // query for video games by platform type
    public static List<VideoGame> getVideoGamesByConsole(String type) throws IOException, XPatherException {
        String query = BASE_URL + type;
        TagNode node = getAndCleanHTML(query);
        List<VideoGame> games = new ArrayList<VideoGame>();
        // insert class value here
        games.addAll(grabGamesWithTag(node, "addToQueueEligible game  sizeb gb6 bvr-gamelistitem    ", type));
        return games;
    }

    private static List<VideoGame> grabGamesWithTag(TagNode head, String tag, String type) throws XPatherException {
        // grab video game names
        Object[] gameTitleNodes = head.evaluateXPath(String.format(TITLE_EXPR, tag));
        // grab preview images
        Object[] imgUrlNodes = head.evaluateXPath(String.format(IMG_EXPR, tag));
        List<VideoGame> games = new ArrayList<VideoGame>();
        for (int i = 0; i < gameTitleNodes.length; i++) {
            TagNode gameTitleNode = (TagNode) gameTitleNodes[i];
            TagNode imgUrlNode = (TagNode) imgUrlNodes[i];
            String title = gameTitleNode.getAttributeByName("title");
            String imgUrl = imgUrlNode.getAttributeByName("src");
            VideoGame v = new VideoGame(title, imgUrl, type);
            games.add(v);
        }
        return games;
    }

    // use HtmlCleaner to grab source code of query URL and clean 
    private static TagNode getAndCleanHTML(String query) throws IOException {
        String content = HTMLNavigator.navigateAndGetContents(query).toString();
        VideoGameScraper.content = content;
        HtmlCleaner cleaner = new HtmlCleaner();
        CleanerProperties props = cleaner.getProperties();
        props.setOmitDoctypeDeclaration(true);
        return cleaner.clean(content);
    }

    public static String getContent() {
        return content;
    }

}

Again, this code is for strictly parsing the site’s data and turning it into VideoGame objects (also be warned that depending on when you read this tutorial, Blockbuster’s underlying code may have changed so there’s no guarantee it will work in the future). To help you guys get a glimpse of why the XPaths work I’ll take a quick screen shot of how Blockbuster’s underlying source code is put together:

XPath Example

Blockbuster Source Code for Scraping

Any ways, now that we have a method for going directly to a URL and scraping the site’s data and turning it into VideoGame objects, we can call it and take the list of VideoGame objects returned and shove it into our database through our VideoGames Wrapper class. The code for this is pretty simple, and here we finally begin piecing together bits of our puzzle:

package app.cronwrappers;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import app.db.DareJDOWrapper;
import app.db.VideoGameJDOWrapper;
import app.scrapers.VideoGameScraper;
import app.types.Constants;
import app.types.DareVideoGame;
import app.types.VideoGame;
import app.types.VideoGame.VideoGameConsole;

// note here we extend the HttpServlet class since we will need to potentially hit this method from external sources
// namely from clients or from cron job runners
public class VideoGameScrape extends HttpServlet {

    private static final long serialVersionUID = 1L;

    private ArrayList<VideoGame> games;

    // method that gets called when we do an HTTP GET request
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        games = new ArrayList<VideoGame>();

        try {
            // grab all games from all platforms using our scrapers
            games.addAll(VideoGameScraper.getVideoGamesByConsole(VideoGameConsole.DS));
            games.addAll(VideoGameScraper.getVideoGamesByConsole(VideoGameConsole.PS2));
            games.addAll(VideoGameScraper.getVideoGamesByConsole(VideoGameConsole.PS3));
            games.addAll(VideoGameScraper.getVideoGamesByConsole(VideoGameConsole.PSP));
            games.addAll(VideoGameScraper.getVideoGamesByConsole(VideoGameConsole.WII));
            games.addAll(VideoGameScraper.getVideoGamesByConsole(VideoGameConsole.XBOX));
        } catch (Exception e) {
            e.printStackTrace();
        }
   
        // HERE WE ADD ALL GAMES TO OUR VIDEOGAME JDO WRAPPER!
        VideoGameJDOWrapper.batchInsertGames(games);
        
        // write back to HTTP requester that scraping was successful
        response.setContentType("text/html");
        response.setHeader("Cache-Control", "no-cache");
        response.getWriter().write("Success");
    }
}

Now, once you have these two methods hooked up, you’ll want a way to automate the scraping process (no one wants to manually call these functions once a week to make sure their database is up to date…) and so that’s where CRON jobs come in. And so for the last part of this tutorial, I’ll show you how to set up a cron job scheduler in Google App Engine. It’s pretty simple really – in your Google App Engine project you just need to go to /war/WEB-INF/ and open your cron.xml file (or create it if you don’t have one).

Then, you just need to put in the following code:

<?xml version="1.0" encoding="UTF-8"?>
<cronentries>

  <cron>
    <url>/videoGameScrape</url>
    <description>Scrape video games from Blockbuster</description>
    <schedule>every day 00:50</schedule>
    <timezone>America/Los_Angeles</timezone>
  </cron>
  
</cronentries>

Which simply tells the scheduler to run your VideoGameScrape method everyday at 12:50 AM PST. It’s pretty simple, but if you want to read more on this subject I’d look at Scheduled Cron Jobs in Java.

In any case, I hope some of this is starting to come together for those of you who have no background in the subject. Next tutorial I’ll show you guys how to piece together the GET/POST requests in Google App Engine so that the cron job scheduler as well as any clients (i.e. mobile phones or websites) can hit your server and call various methods for retrieving data / uploading data.

Comments and feedback always welcome! Happy coding everyone.

[UPDATE]

So I just realized that no where on my blog do I actually give code for my HTMLNavigator class. It’s a really simple class… more of a wrapper around a bunch of helper methods that I use to navigate across websites and grab content. The method that’s most important though is the following:

public class HTMLNavigator {

    public static CharSequence navigateAndGetContents(String url_str) throws IOException {
        URL url = new URL(url_str);
        URLConnection conn = url.openConnection();
        String encoding = conn.getContentEncoding();
        if (encoding == null) {
            encoding = "ISO-8859-1";
        }
        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), encoding));
        StringBuilder sb = new StringBuilder();
        try {
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
                sb.append('\n');
            }
        } finally {
            br.close();
        }
        return sb;
    }

}

And so it’s basically just a wrapper around some stream readers and content settings. In fact you could probably argue that the task is simple enough to not need a wrapper like this… but I write numerous applications which require/leverage web content retrieval and so having this class around in my projects has saved some time. Hope this all makes sense!

- jwei

Google App Engine – The Backend (1)

November 1, 2011

Hey everyone!

So here we go with Part I of the series! Again, this post will focus on defining a very simple object (in my case, I’ll use a very simple VideoGame object which I used for my actual application) and then creating a series of wrappers in your Google App Engine project to allow you to add/remove/update entries in your server’s database. But before I get ahead of myself – let’s start from the beginning.

So what exactly is Google App Engine and why do I need it?

From their website:

Google App Engine enables you to build and host web apps on the same systems that power Google applications. App Engine offers fast development and deployment; simple administration, with no need to worry about hardware, patches or backups; and effortless scalability.

Simply put, setting up a Google App Engine project allows you to create a server that is hosted in the “cloud”. This server comes with a very convenient and scalable database, and gives you the ability to interact with this database through standard HTTP requests.

Why is this useful as an Android developer? Well, aside from the obvious answers of the necessity for having a centralized database in order to develop any kind of large scale data-centric application, because any Android application is limited by the memory and processing powers of the phone itself, it’s far from ideal to do any kind of heavy data scraping or to maintain any kind of large SQLite database on the phone.

Now time to dig into the code.

Let’s start with my simple object class called VideoGame – note that this object class will look slightly different from the normal Java class object as we need to define a couple of annotations which allow the object to be stored in Google App Engine’s database:

import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;

import com.google.appengine.api.datastore.Link;

@PersistenceCapable
public class VideoGame extends ModelBase {

    // note the Persistent tags
    @Persistent
    private String name;

    @Persistent
    private Link imgUrl;

    @Persistent
    private int consoleType;

    public VideoGame(String name, String url, String consoleType) {
        this.name = name;
        // note the App Engine class Link - simply a wrapper around URL strings
        this.imgUrl = new Link(url);
        this.consoleType = VideoGameConsole.convertStringToInt(consoleType);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Link getImgUrl() {
        return imgUrl;
    }

    public void setImgUrl(Link imgUrl) {
        this.imgUrl = imgUrl;
    }

    public int getConsoleType() {
        return consoleType;
    }

    public void setConsoleType(int consoleType) {
        this.consoleType = consoleType;
    }

    public static class VideoGameConsole {

        public static final String XBOX = "Xbox";

        public static final String PS3 = "Ps3";

        public static final String WII = "Wii";
        
        public static final String[] CATEGORIES = { XBOX, PS3, WII };
        
        public static int convertStringToInt(String type) {
            if (type == null) { return -1; }
            if (type.equalsIgnoreCase(XBOX)) {
                return 0;
            } else if (type.equalsIgnoreCase(PS3)) {
                return 1;
            } else if (type.equalsIgnoreCase(PS2)) {
                return 2;
            } else {
                return -1;
            }
        }

        public static String convertIntToString(int type) {
            switch (type) {
                case 0:
                    return XBOX;
                case 1:
                    return PS3;
                case 2:
                    return PS2;
                default:
                    return null;
            }
        }
    }

}

And just quickly here’s the ModelBase class that it extends:


import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.Inheritance;
import javax.jdo.annotations.InheritanceStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
@Inheritance(strategy=InheritanceStrategy.SUBCLASS_TABLE)
public class ModelBase {

    // in any standard database, each row needs to have a unique ID
    // this ModelBase class defines a long ID that each VideoGame object will inherently have
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;
	
	public Long getId() {
		return id;
	}
}

Now, it might seem like a lot of code, but let’s just break the important parts down piece by piece. First off in the ModelBase class we’re simply defining a generic class of objects which contain an ID. Like in all databases, each row must have a unique ID so that it can be identified, and in our case since Google App Engine uses a JDO (Java Data Objects) database (meaning rows are represented as Java objects) each new object we create must have its own ID. If you have any background in SQL then you’ll immediately recognize key words like PrimaryKey which will give you a big hint at what this initial ModelBase class is doing. You’ll also see that there’s a @Persistent tag, and in Google App Engine, when you define a field to be persistent you are simply telling the database to store those values. In other words, you’re essentially defining a new column in your database.

Now, once you understand these initial basics, the rest is pretty self explanatory. Here in my VideoGame class, I simply extend ModelBase to make it a valid row object with a unique ID (this ID will automatically get set for you upon adding it to the database) and then declare the object @PersistenceCapable. Again, this is simply telling the Google App Engine database that this VideoGame object should be store-able, or going back to SQL speak you’re basically creating a new table called VideoGame here which will store VideoGame rows.

I then make a couple of fields persistent (i.e. defining columns in my table) and add some simple helper methods and voila! Now I can go ahead and start adding these VideoGame objects into my database (for a less verbose and more technical set of explanations, Google has posted this tutorial, also very good).

The code for the JDO wrapper (as I call it) is:


// wrapper for storing/deleting/updating VideoGame objects
public class VideoGameJDOWrapper {

    // insert a single video game
    public static void insertGame(VideoGame g) {
        // check to make sure this game doesn't already exist
        boolean exists = checkGameExists(g);
        if (!exists) {
            PersistenceManager pm = PMF.get().getPersistenceManager();
            try {
                pm.makePersistent(g);
            } finally {
                pm.close();
            }
        } else {
            System.err.println("ERROR: Duplicate attempt");
        }
    }


    // when adding multiple video games, a batch insert is more efficient
    public static void batchInsertGames(List<VideoGame> games) {
        List<VideoGame> toInsert = new ArrayList<VideoGame>();
        for (VideoGame g : games) {
            boolean exists = checkGameExists(g);
            if (!exists) {
                toInsert.add(g);
            }
        }
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            // only add the games which don't exist already
            pm.makePersistentAll(toInsert);
        } finally {
            pm.close();
        }
    }


    // example for retrieving rows - in this case by platform
    public static List<VideoGame> getGamesByPlatform(String platform) {
        // find the numeric type of the platform
        int type = VideoGameConsole.convertStringToInt(platform);

        // open the persistence manager
        PersistenceManager pm = PMF.get().getPersistenceManager();

        // initiate a new query for the VideoGame class
        Query query = pm.newQuery(VideoGame.class);

        // in SQL - this filter is equivalent to a WHERE statement
        // essentially, here we have a column called consoleType (defined earlier)
        // and we are about to pass it a value
        query.setFilter("consoleType == inputType");

        // define what parameter you're going to input
        query.declareParameters("int inputType");

        List<VideoGame> ret = null;
        try {
            ret = (List<VideoGame>) query.execute(type);
        } finally {
            query.closeAll();
        }

        // at this point, you should have a List of VideoGame objects
        return ret;
    }


    // deleting all games with a certain console type
    public static void deleteGamesByType(String platform) {
        int type = VideoGameConsole.convertStringToInt(platform);
        PersistenceManager pm = PMF.get().getPersistenceManager();
        Query query = pm.newQuery(VideoGame.class);
        query.setFilter("consoleType == inputType");
        query.declareParameters("int inputType");

        // up to this point, defining the query is identical to the GET request above
        // only difference is in the method we call with this query
        query.deletePersistentAll(type);
    }


    // wrapper to check if a video game exists
    private static boolean checkGameExists(VideoGame g) {
        PersistenceManager pm = PMF.get().getPersistenceManager();

        // I defined an identical game if it had the same name and was on the same console
        Query query = pm.newQuery(VideoGame.class, "name == gameName && consoleType == gameType");
        query.declareParameters("String gameName, int gameType");
        List<VideoGame> ret = null;
        try {
            ret = (List<VideoGame>) query.execute(g.getName(), g.getConsoleType());
        } finally {
            query.closeAll();
        }
        return !ret.isEmpty();
    }

    
    // if you have the row ID of the VideoGame then
    // there's a simple way to retrieve the associated object without defining a query
    public static VideoGame getVideoGamesById(long id) {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        return (VideoGame) pm.getObjectById(VideoGame.class, id);
    }


    // this is also the most practical way to update an object
    public static boolean updateVideoGameName(long id, String newName) {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        boolean success = false;
        try {
            // how the persistence manager works is that as long as it is OPEN
            // then any chances to an object will AUTOMATICALLY GET UPDATED AND STORED
            VideoGame v = (VideoGame) pm.getObjectById(VideoGame.class, id);
            if (v != null) {
                v.setName(newName);
                success = true;
            }
        } catch (JDOObjectNotFoundException e) {
            e.printStackTrace();
            success = false;
        } finally {
            // however once you CLOSE the persistence manager, then any updates to the object
            // will not be reflected in the database
            pm.close();
        }
        return success;
    }

}

And again for the sake of completeness here’s the code for the Persistence Manager (taken straight from the Google App Engine tutorial):


import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

public final class PMF {

    // this is a singleton which acts as a gateway to the database itself
    private static final PersistenceManagerFactory pmfInstance = JDOHelper
            .getPersistenceManagerFactory("transactions-optional");

    private PMF() {
    }

    public static PersistenceManagerFactory get() {
        return pmfInstance;
    }
}

So there you have it! Everything hopefully should be pretty self explanatory. But just to summarize, I’m going to assume that most people out there have some experience with SQL (or variants of SQL) and so I’ll pair each step in the Google App Engine process with its equivalent step in setting up a SQL database:


1. Defining a Persistence Manager -> Opening a connection to your SQL database

2. Defining a PersistenceCapable object -> CREATE TABLE in SQL (and like in SQL – you need a column for Primary Key)

3. Defining Persistent fields -> creating columns in a SQL table

4. Defining a Query object that returns/deletes a list of Java objects -> defining a SQL query that returns/deletes a sub-table of rows

5. Specifying a Query object’s filters -> including a WHERE filter in a SQL query

6. Retrieving an object from the Persistence Manager and changing a field before closing the PM -> retrieving a row in SQL and updating a field

And I think that just about wraps it up – probably my longest post to date and yet I feel like I could still go into more detail for a few parts, but hopefully you guys get the picture.

Happy Coding! Part II up next.

- jwei

Google App Engine? What?

October 16, 2011

Hey everyone!

It’s been a while – I admit I’ve been lazy with coming up with new ideas: it’s been quite a transition leaving school in June and coming all the way out to New York for my first job.

But in any case I’m excited to announce a new series of posts that I’d like share with everyone! I’m deviating a tad away from the Android only theme by introducing a series of tutorials on how to first design a back end using Google App Engine, and then on pulling everything together to make an Android client as the front end!

To lead me through these series of tutorials, I’ve decided to unwrap an application that me and my friends worked on for a competition we won last year:

http://juicyideascompetition.appspot.com/

So if you’re new to Android and/or Google App Engine, or if you’ve never built an application from beginning to end, then this series might be for you.

The order that I’ll be writing the posts will be as follows:

Application Design Process

Application Design Process

So I’ll be starting with a look into (1) Google App Engine (I won’t be covering the actual set up process which is pretty easy and Google has some nice tutorials for that) and how to set up a JDO database and write wrappers for inserting/removing objects to/from the database. I’ll then move onto how to actually (2) collect data for your database by writing scrapers and automating them by setting up cron jobs. From there I’ll give a few examples on how to (3) write HTTP GET/POST requests from both the client perspective and the servlet perspective. And lastly I’ll bring it all together by giving some client end examples on (4) making HTTP requests, receiving them, parsing the data from them, and then displaying this data.

Hopefully it won’t take too long to get through all these posts, though I expect to work on them throughout the month. But yes, always welcome to more suggestions but hope people are as excited about this as I am!

Happy coding,

jwei

Follow

Get every new post delivered to your Inbox.

Join 887 other followers