Google's AI Challenge

It is that time of year again that Google is sponsoring an AI challenge - It's a standard affair, you have to controll a set of ants and collect food and eventually defeat other ant hills, but its good fun and always a good opportunity to play around programming in a more competitive environment.

Full details are here, you can download the starter pack and get started in lots of programming languages, but unsuprisingly I have gone with Java for now - once you have the pack downloaded, they have some steps they recommend to get your ants doing the basics well, although you will obviously want to go beyond this minimum set, its a good chance to get your head around the object model and the APIs that are provided as standard.

I have just started this today and have completed the first 4 steps of the walkthrough, so not even started thinking about personal tactics and strategy.. so expect some posts to follow with those.

In the meantime, I am, as always, keeping my code on GitHub, so feel free to have a poke around how I have implemented the various steps in my code (only the first step of the tutorial is implemeneted in Java at the moment, the others are all currently in Python, so does require the slightest bit of imagination)

2 comments:

Integrating MongoDB & Spring

Further to my previous post with a deck walking through MongoDB & Spring integration, I also recently wrote it up as a technical article for work (my day job), and I thought I would share the detailed article here for you as well..


Introduction

With the explosion in the amounts of data being generated in recent years, more and more organisations are looking at alternative data storage options to the traditional relational model. This in turn has lead to huge growth in the NoSQL space, with leading web companies such as Facebook, Google, Twitter, Reddit, etc adopting NoSQL solutions.
Within the NoSQL space there are several different implementation options (Graph based DBs such as Neo4J, Wide Column DBS such as Cassandra and Haddop, Document based DBs such as MongoDB and CouchDB) and careful consideration is needed before choosing an implementation.
This article will look at integrating the Document oriented database MongoDB with a Spring MVC Web Application – it is important to note that due to the nature of Document based storage solutions, they are not applicable for all problems. For example, if the data you are modelling cannot naturally be stored as “documents”, then a Document-oriented DB probably isn’t the best solution (an easy way to think about whether the model can be stored as a document is to think of it being stored on paper – does it make sense for all the elements to be intrinsically grouped in to a single document? E.g. if you were storing an essay, all the chapters are intrinsically linked to the essay as a whole document, and a single chapter doesn’t make much sense as an individual object on its own).
For that reason, this article will look at a simple web app that allows users to create Resumes – Similar to an essay, resume storage is naturally suited to the Document based approach rather than a Relational approach.


Getting Started

This article will not cover details of creating a Spring MVC web application, and will assume a prior knowledge of the Spring MVC framework and core Spring principles. The example application itself is very simple, and there are several aspects of it that have not been included (these have been intentionally left out for simplicity), such as security/authentication features, advanced UI/screen flow/editing, etc, the purpose of the example application is purely to demonstrate MongoDB integration with Spring.
The source code for the application is all available from my GitHub Account (see links on the right), and if you want to follow the code below are the required pre-requisites:
  • Install MongoDB – this is a straight forward process and details can be found here: http://www.mongodb.org
  • Install Maven – the example project uses Maven to manage it dependencies, details can be found here: http://maven.apache.org/
  • Install STS Eclipse build and install the CloudFoundry extension (Optional) – If you want to follow the steps to deploy the application to the cloud then this is required
  • Sign up for a CloudFoundry account (www.cloudfoundry.com) (Optional) – Currently in Beta so its recommended that you sign up for the account as soon as possible as requests can take time to come through






Project Dependencies

Spring currently has a project underway to integrate core Spring functionality with various non–relational data technologies, including MongoDB, called “Spring Data”. We will use this library to facilitate our integration, so we will need to include the following maven dependency in our project pom:

              <dependency>
                     <groupId>org.springframework.data</groupId>
                     <artifactId>spring-data-mongodb</artifactId>
                     <version>1.0.0.M3</version>
              </dependency>


We also need to include the MongoDB Java driver:

              <dependency>
                     <groupId>org.mongodb</groupId>
                     <artifactId>mongo-java-driver</artifactId>
                     <version>2.6.5</version>
              </dependency>


And finally, to deploy on to CloudFoundry’s hosted service we need their runtime library:

              <dependency>
                     <groupId>org.cloudfoundry</groupId>
                     <artifactId>cloudfoundry-runtime</artifactId>
                     <version>0.7.1</version>
              </dependency>




Building the Domain Model

If you are familiar with using popular JPA frameworks in your Spring web apps (Hibernate/Eclipselink, etc) then this part should look familiar – Like any application we will need to create some objects to model our underlying data (the “M” in the MVC). For our simple application we will have three basic objects:



As you can see, we have three simple objects in our model, Resume, ResumePage, Section (we will just use these objects to split our document down in to several sections/chapters). One of the advantages of using Document-oriented DBs is that as it is schema-less, objects can be added to the document in the future without affecting existing data.
We model these objects as simple POJOs, just like modelling entities in JPA, but there are a few simple annotations Spring-Data provides for us
Resume.java:

@Document
public class Resume {
      
       @Id
       private String id;
      
       private List<ResumePage> pages = new ArrayList<ResumePage>();
...


That’s it! We use the @Document and @Id annotation to indicate any object that we want to treat as a Document, and the ID. We only need to add these annotations on our Resume object, as in this case the Resume is our document, we do not want to store our pages or sections as individual documents in themselves.



Data Access Layer

Now we have our data model we need to create our Data Access layer, so we can easily perform CRUD updates on our documents.
Creating our Data Access Objects is incredibly simple using MongoDB’s MongoRepository, and we automatically get basic CRUD functionality by just extending that interface. In our example app, we only want CRUD functionality so we just create a basic Interface that extends MongoRepository:

@Transactional
public interface IResumeRepository extends MongoRepository<Resume, String>{}

Next, in our Service layer we will auto-wire our new Interface in to our service classes (this is normal Spring stuff, using the @Autowired annotation we are telling Spring to handle the dependency injection for this interface):

@Repository("profileService")
@Transactional
public class ProfileService{

       @Autowired
       private IResumeRepository resumeRepo;


This makes the CRUD functionality available in our Service class to perform common functions, such as loadResume (in this case, we are using the resume owner’s name as the ID for the documents):

public Resume get(String userName) {
       return resumeRepo.findOne(userName.toLowerCase());
}


Or createResume:

       public Boolean createResume(Resume r) {
              try {
                     // Insert to db
                     resumeRepo.save(r);
                     return true;

              } catch (Exception e) {
                     //log exceptions here!
                     return false;
              }
       }


By simply extending the MongoRepository Interface and then auto-wiring it into our Service classes, we have provided basic CRUD functionality through the MongoRepository API as well as ensuring that our service class is not tightly coupled with the DAO implementation. However, often applications will need custom queries beyond basic CRUD. This can also be simply achieved using the MongoTemplate class provided, for example:

Query query = new Query(where("id").is(“rob”));
Resume r = mongoTemplate.findOne("mycollection", query, Resume.class);

The above query will retrieve the Resume belonging to “Rob”. The Query object provides rich API for accessing and updating documents in your data store.



Spring Configuration

The final step of our integration is to configure the Spring beans to handle the data source properties.
The Spring configuration resides in the Application Context XML file (in our case, it’s a file named “applicationContext.xml” and can be found in src/main/resources/META-INF/spring/.
This file is used to declare some of the Spring beans (although not all beans will be declared in here – some beans are declared using annotations, such as our Service classes), for our MongoDB integration we need to include the following configuration:

       <!-- Mongo Configuration -->
       <mongo:repositories base-package="com.tmm.nosql.mongodb.repo" />
      
       <bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
              <constructor-arg ref="mongoDbFactory" />
       </bean>
      
       <!-- local config -->
       <mongo:db-factory id="mongoDbFactory" dbname="resume_db" host="localhost" port="27017"/>


The first element of the config declares the name of the package that our Repositories are stored in (this is where the our DAO Repository lives) – we declare this so to enable the package to be scanned for relevant repository classes.
The second configuration element declares the Mongo Template bean (provided by the Spring Data library) and we declare that we want Spring to inject our MongoDbFactory bean using Constructor based Dependency Injection.
The final configuration option declares the MongoDbFactory that we will be injecting in to our MongoTemplate bean – here we need to define the database server and port name. The default port number is 27017, so unless you have altered from the standard MongoDB install and configuration then you should use these details.




Running the Application

Running Locally

To test the application, set up a Tomcat server within your Eclipse (IDE) and add the project to the server, start the server and navigate to http://localhost:8080/ and you should see a simple welcome page.

Running on CloudFoundry

Before running on CloudFoundry we need to make a very minor tweak to the configuration. Previously we had added the configuration option:

<mongo:db-factory id="mongoDbFactory" dbname="resume_db" host="localhost" port="27017"/>

As we are no longer running on localhost and want to bind these options to CloudFoundry’s services, we change this to:

<cloud:mongo-db-factory id="mongoDbFactory"/>

Simple enough again – we just declare our MongoDbFactory, and leave CloudFoundry to inject the required parameters.


The next step to deploying the application on CloudFoundry is to add a CloudFoundry server instance to your eclipse:
  • Open the “Servers” view in Eclipse (Window>Show View>Servers)
  • Right-click and select New>Server

  • Select VMWare > Cloud Foundry and then press the “Next” button
  • You will then have to enter your Cloud Foundry account information:



  • Complete your email and password information, leaving the URL as it is and select the Next button.
  • The final screen will give you the option to add the project to the server, add the server and press Finish



Now the Cloud Foundry server instance is setup within your IDE you need to configure the deployed application so you can bind it to the required services:
  • Double-click on your deployed project within the “Servers” view:


  • This will open the “Applications” page – you will notice in the bottom left had corner an empty box titled Services, 




  • Press the “Add Service” button to the top right of the Services panel:




  • The MongoDB service will now be listed in the Services box, now drag it across to the right to the “Application Services” section. The “Applications” panel should now appear something like this:



  • Press the “Start” button under the General tab, then watch the log as the application is started up on the CloudFoundry – there should be no errors reported
  • Now navigate to the URL you assigned to the application (this can be edited in the above panel under the “General” section


You now have a MongoDB powered NoSQL application running in the Cloud!

0 comments:

Side Project - An Update

Here is a very early introductory slide on what the side project is all about, along with some screen-shots (the look and feel has been updated and in my oppinion is pretty nice!)
The link to the project blog is still the same at.. http://butterfly-software.blogspot.com/

0 comments:

Moving to GitHub



Despite usually being a commited (no pun intended) svn user I have decided to make the switch to Git & GitHub.

There were two main reasons, one was just a curiousity to see what Git was all about and see how it worked, and the other was that I just really wanted to start using GitHub.

My GitHub profile is here: https://github.com/robhinds

As a starting point, I have moved all my demo source code over to GitHub, so that can all be accessed directly from there (although the old links will still all work).

If you head to my profile you will also see a few repositories associated to a RoR tutorial that I am currently working on - so there will be a post coming out of that shortly..

0 comments:

Hands On NoSQL - Integrating MongoDB & Spring MVC


Over the weekend, I took some time out of my side project to have a play with MongoDB. I was interested in looking at NoSQL and getting my head around some of the implementation details and had heard document oriented NoSQL DBs would be a good place to start.

So I stripped out the guts of a web app I have built, and dropped in a very simple domain model (the app just allows creation of resumes - I chose it as I wanted a model that made sense to use a document oriented DB rather than trying to crowbar in a model that is still relational) - then using Spring I looked at wiring all the MongoDB stuff. I was pleasantly suprised with how easy it was to drop it all in.

This also gave me a chance to finally play with CloudFoundry - I've had my beta account for a while now, but seeing as CF supports MongoDB and Spring/Java apps I figured this would be a perfect chance to test it out. Again, it was relatively easy to configure the app and CF to get the app up and running using the Clouds mongo DB service.

The other bit of experimentation I have done is rather than writing this up in a massive blog post, I have signed up for slideshare and uploaded a presentation with the details - you can check out the presentation embedded above - would love to hear feedback as to whether you prefer slideshows or traditional blog posts - for me its harder to get a lot of details in slides without over-crowding them, but then if its a very detailed walkthrough it can make for an over-long blog post.

As always, the complete source code for the app (Spring MVC web app with full mongoDB configuration, including config for both localhost and CloudFoundry deployment) is available here!

2 comments:

Free Stanford Courses

As I have mentioned before, I am a big fan of Stanfords online efforts of putting lectures/courses in places like iTunes for free.

They have now announced that they will be offering several of the courses fully online, for free - this includes lectures (in real time) and all the coursework, which will be marked and graded, and all students will be informed on how they rank (in terms of percentiles i guess). The course doesn't get any official Stanford credit, but will get a "Statement of Accomplishment" (whatever that is).

The list of courses currently about to be offered this coming academic year is here

Having a degree in Artificial Intelligence, I would love to sign up for the AI courses to refresh (its been several years since uni and AI has changed a lot), but not sure I could find the time to keep up with further weekly commitments and coursework, but will investigate further.


0 comments:

API Design Manual

3:12 PM , , 0 Comments

Came across quite a useful document via HN a week or two back covering good API design that is worth a read if you are involved in software development.

Check it out here

0 comments:

Software Engineering Interview Questions Part 2

There was also recently an article that was doing the rounds with the 20 most craziest interview questions, quoting allegedly real questions from interviews at places like Google, Facebook, Goldmans etc. Here are a few, along with my attempts to answer them..

Facebook: Twenty five racehorses, no stopwatch, five tracks.  Figure out the top three fastest horses in the fewest number of races.
This needs a few assumptions before we begin: 1) each track only races 5 horses, and races cant be started at the exact same time - preventing effectively just running all the horses at once; 2) horses run the lap in a consistent time (e.g. if horse A beats horse B in one race, and horse B then beats horse C, then A will also beat horse C)
  1. Race 5 races, each with 5 horses in it (so all horses have raced) (5 races)
  2.  Race 1 race with the winners of the first 5 races (6 races)
  3. Find the winner of race 6 and from that horse's original race take the horses that came second and third (2 horses); take the second place horse of race 6 plus the horse that came second in his original group (2 horses); take the third place horse of race 6 (1 horse) - Race these 5 horses, this will give the second and third fastest horses (we already know the number 1 fastest horse is the winner of race 6)
Total races: 7

Goldman Sachs: Suppose you had eight identical balls. One of them is slightly heavier and you are given a balance scale. What’s the fewest number of times you have to use the scale to find the heavier ball?
Answer: 2
  1. Arbitrarily split the balls in to three piles, 3-3-2
  2. weigh the two sets of 3 balls (first weighing)
  3. If the two sets of three balance (weigh the same) then we know the heavier ball is one of the balls in the set of 2, so weigh those two (second weighing), and you will see immediately which is heavier
  4. If the two sets of three do not balance, then take the heavier set and weigh any two of those balls - if the first two balls you weigh are the same then you know the third ball in the set of 3 is the heaviest. If they do not weigh the same then you will immediately see the heaviest ball


Google: You are climbing a staircase. Each time you can either take one step or two. The staircase has n steps. In how many distinct ways can you climb the staircase?
The trick to this question, as with a lot of complex sounding questions(things that start with "there are 100 prisoners.." or "there is a village with 1,000 married couples") is to break "n" (or the number provided" to a much lower number.

In this case, lets start off with n=2 (we will skip n=1) - in this instance its easy to do the mental arithmetic to work out the number of permutations: it can be 1,1 or 2. So therefore there are 2 different permutations. Obviously, in this case, whilst n=2, permutations(lets call it x)=2, but its safe to assume n=x will not be consistent as n increases.

So let's increase n, this time, n=3. Again, simple mental arithmetic and we can work out possible permutations: 1,1,1;  1,2 and 2,1. So again there are 3 permutations (x=3).
We will continue our approach to see if we can see a pattern emerging.

n=4: possible permutations: 1,1,1,1;  2,2;  2,1,1;  1,2,1;  1,1,2, so x=5
n=5: possible permutations: 1,1,1,1,1;  2,2,1;  2,1,2;  1,2,2;  1,1,1,2;  1,1,2,1;  1,2,1,1;  2,1,1,1;  So x=8

We could continue this process untill we could see a pattern emerging, although as n increases, the number of permutations increases so might need a pencil and paper if you wanted to carry on. Fortunately, it seems to be heading in the direction of the Fibonnaci sequence! So to find the number of permutations for n steps we just need to find the nth position in the fibonnaci sequence (still not that simple!)



I have not validated that these answers are correct, but this is what I came up with! Leave a comment if you think I have done something wrong somewhere along the way.

0 comments:

A Side Project

I have been working on a side project for what seems like forever now, but I have set up a blog dedicated to it. All it currently has on it is a few screenshots and an introductory post about what exactly it is, but you can check it out here.

The source code isn't actually available yet as its not even in beta yet, but I'm hoping it will surface before the end of the summer. Would love to hear peoples thoughts on the project!

0 comments:

A New App - Photo Effects and Filter Library



Recently I started looking at experimenting with the camera and manipulating images on the Android platform, and after a few weeks of experimenting I have finished and released a new app to the market that lets users capture still images and then apply a selection of filter/fx to their pictures.

It's a simple app, and is just a bit of fun for the user - the effects available are things like outline, neon, invert, b&w, pixelate, etc. There are more details about the app and some demo pictures on the page linked at the top of the blog entitled cutting room.

My experimentation started simply with playing about with some of the many Java image filter and effects libraries that are available such as Marvin and JH Labs. The Problem you find immediately when trying to link these up with your Android app is that the Android JRE does not include the core java AWT package. This limits the use of practically every image filtering library available as they all use java.awt.BufferedImage and the rest of the awt package.

Instead of the BufferedImage class, the Android platform provides its Bitmap class, and looking through the filter classes, it seemed like it should be fairly straight forward to port some of them over to Android, so I went with the Marvin library.

You can check out my final effects app the "Cutting Room" on the market, but I have also released the ported Marvin effects code on google code as open source, so feel free to check that out and use it for anything you feel fit!

I will post again soon walking through setting up an app to use the camera, so stay tuned for that.

0 comments:

Android & Twitter - OAuth Authentication Tutorial

I’ve seen a lot of questions about connecting Android apps with Twitter using OAuth and thought I would write up a walkthrough of how it can be done. The example will be done using Twitter4J which is a great library for connecting Java apps with Twitter and provides a simple interface to connect to the public Twitter Web Services.

First thing you will need to do is to register your new app (even though you haven’t made it yet!). Do this by heading to https://dev.twitter.com/apps/new (you will need an existing Twitter account sign up). You should complete the form with the relevant details for your app:


You should fill in your details for the application such as name, description, URL – but the only key things to remember to do here are as follows:

1) Make sure you select “Browser” as your application type – even though we are creating an app, we will authenticate using the browser and a callback URL.

2) Tick read & write permissions

Once you have registered you will be provided with a “Consumer Key” and a “Consumer Secret” – make note of these for later – we will need to include these in the app.


Now let’s get started with the app! I will assume for this tutorial that you are familiar with the basics of Android apps so won’t go into details about how to setup the UI and what an Activity or Application is.
The first thing we will do is create an Activity that will prompt the user to login to Twitter and authorize the app to connect to Twitter to make updates. Let’s start with the onCreate method:


@Override
public void onCreate(Bundle savedInstanceState) {
 System.setProperty("http.keepAlive", "false");
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main_oauth);
 
 //check for saved log in details..
 checkForSavedLogin();

 //set consumer and provider on teh Application service
 getConsumerProvider();
 
 //Define login button and listener
 buttonLogin = (Button)findViewById(R.id.ButtonLogin);
 buttonLogin.setOnClickListener(new OnClickListener() {  
  public void onClick(View v) {
   askOAuth();
  }
 });
}

The first line we set the http keepAlive property – this is important so the app manages the connection correctly without reseting. The next important thing is our call to the checkForSavedLogin() method – this is a method that checks whether the user has previously authorised the app to access twitter, in which case we can just proceed as usual to the default twitter timeline activity (we will have a look at that method next). Otherwise we just initialise the Consumer/Provider and store them in our Application class so they are available to all Activities throughout the application. Then finally we inflate the button on the page and set a listener to call the askOAuth() method on click.


Now let’s jump in to the checkForSavedLogin() to see whats going on there:

private void checkForSavedLogin() {
 // Get Access Token and persist it
 AccessToken a = getAccessToken();
 if (a==null) return; //if there are no credentials stored then return to usual activity

 // initialize Twitter4J
 twitter = new TwitterFactory().getInstance();
 twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
 twitter.setOAuthAccessToken(a);
 ((TwitterApplication)getApplication()).setTwitter(twitter);
 
 startFirstActivity();
 finish();
}



This method calls a method getAccessToken() – all this does is check in the user SharedPreferences to see whether we have stored the users AccessToken previously – if there is no token found it just returns, so the user is left on the authentication activity waiting input.

However, if a token is found, then we initialise Twitter4J Twitter object and store that in our Application class (again, so we can use it throughout the application).
Finally we call startFirstActivity(), which simply calls the default Twitter timeline activity we have and finishes the authentication activity as it is not needed.

So that is all good, if the user has previously authenticated then no probs – however, if no saved token is found the user still needs to authenticate so we need to handle the user action (remember we are calling the askOAuth() method from within our button listener).



Let’s have a look at that method – this is where the authentication is all done:

private void askOAuth() {
 try {
  consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
  provider = new DefaultOAuthProvider("http://twitter.com/oauth/request_token", "http://twitter.com/oauth/access_token", "http://twitter.com/oauth/authorize");
  String authUrl = provider.retrieveRequestToken(consumer, CALLBACK_URL);
  Toast.makeText(this, "Please authorize this app!", Toast.LENGTH_LONG).show();
  setConsumerProvider();
  startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)));
 } catch (Exception e) {
  Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
 }
}

First thing we do here is to initialise the Consumer and Provider objects – we are using the Commons OAuth Consumer/Provider (so you need to make sure you copy the following JARs in to your /assets/ directory and then add them to your build path: “signpost-commonshttp” and “signpost-core”).

You will see that the consumer is initialised using to static Strings CONSUMER_KEY and CONSUMER_SECRET – these need to be set to be the key and secret Twitter provided when you registered the app – you should make sure you keep these secret and not reveal them to people.

The provider is then just initialised using the relevant URLs that Twitter provides to authenticate againse.

Next, we call the retrieveRequestToken() method on the provider object, this takes two arguments: the consumer, and the CALLBACK_URL (another static string) we will come back to what this is later.

We then call startActivity with a new Intent using the authenticate URL – this is what will forward the user to the Twitter authentication service for them to securely login and authorize the app to make updates for them.



So now, we have a simple authentication activity, that if the user has never logged on before will forward them on to the Twitter OAuth service – next we need to handle the response from Twitter and if a successful response received, then store the Access Token for future use. This is all done in the onResume() method:

@Override
protected void onResume() {
 super.onResume();
 if (this.getIntent()!=null && this.getIntent().getData()!=null){
  Uri uri = this.getIntent().getData();
  if (uri != null && uri.toString().startsWith(CALLBACK_URL)) {
   String verifier = uri.getQueryParameter(oauth.signpost.OAuth.OAUTH_VERIFIER);
   try {
    // this will populate token and token_secret in consumer
    provider.retrieveAccessToken(consumer, verifier);

    // Get Access Token and persist it
    AccessToken a = new AccessToken(consumer.getToken(), consumer.getTokenSecret());
    storeAccessToken(a);

    // initialize Twitter4J
    twitter = new TwitterFactory().getInstance();
    twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
    twitter.setOAuthAccessToken(a);
    ((TwitterApplication)getApplication()).setTwitter(twitter);
    //Log.e("Login", "Twitter Initialised");
    
    startFirstActivity();

   } catch (Exception e) {
    //Log.e(APP, e.getMessage());
    e.printStackTrace();
    Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
   }
  }
 }
}


First thing, the method checks that the intent that has called the onResume is the expected intent, and then pulls out the verifying string from the callback URI – it then uses this string to retrieve the access token. Once we have called the retrieveAccessToken() method, we can initialise an AccessToken and store it. Next we initialise the Twitter4J object with the CONSUMER_KEY and SECRET again and then set the Access Token – once this has all been setup we just start the first activity as normal.
Once the user has authenticated they will be forwarded to the their friends timeline!

Now, the only thing remaining, is that we need to tell the app that once Twitter has finished authenticating that it needs to return to our Authentication Activity to call the above onResume method, or else it won’t be able to continue. To do this, Twitter will attempt to use the CALLBACK_URL we saw earlier. If you remember, when we requested the token from Twitter we passed in the CALLBACK_URL. I have previously defined this as follows:

private String CALLBACK_URL =           "callback://tweeter";

The name of the callback is up to you (I have named it “tweeter”), what is important is that this matches the callback you define in your Manifest XML. For the welcome activity (our Authentication activity) it needs to be defined as follows:


 
  
  
 
 
  
  
  
  
 



As you can see, we have defined an intent-filter with a scheme called “callback” and we provide the host name as “tweeter” – matching that used to call the Twitter service.

And thats it! The user has been authenticated and returned to our application correctly, so it can now continue to read timelines, post tweets, retweet, etc.



The complete source code of the application is available here (NOW ON GITHUB!), please note that I have removed my own CONSUMER_KEY/SECRET details, so to make this work you will need to register your app and populate with your own details to see it work in your emulator/device.

71 comments:

Getting Started - A Complete Android App walkthrough for Beginners (Part 2)

This is part 2 of a walkthrough of one of my first ever Android app, that happened to get a little bit of love in the android market, and for which the ENTIRE(!!) source code of the application is available to you good people to do whatever you want with.. see part 1 for more details of the app, what happened and the first steps in getting started!

So far, we have created a simple Activity class, designed a layout with several buttons and then implemented an onClickListener within our Activity class to handle the required actions for all of our buttons. The remaining Activities are all fairly straight forward, and work in a similar fashion: the RulesActivity is just a simple activity what has a block of text with a brief description of the game; the SettingsActivity is a simple activity that has three radio buttons which allows the user to select the difficulty; the QuestionsActivity just displays a question and then a selection of multiple choice answers.

If you are not familiar with Activities then you can open up those other classes and see exactly what is going on, they are all pretty similar but each have slight nuances or differences in their components and actions.

At the moment the application is pretty simple – there is a basic welcome screen with some buttons, and once you start the game you get taken through the QuestionsActivity several times, refreshing with different questions until you have answered all the questions, and then at the end it displays a simple graphic based on your accumulated score. Easy right?!

Really, the only big gap in what is going on is the DB – all the questions need to be stored in the DB on the client device, and then that data needs to be accessed, so we basically need a DAO type class.

In this app, we have a single DBHelper class – you may want to wrap this with a service class, to allow better separation of layers and decreased coupling etc, but for the sake of this app, lets just jump into the DBHelper. To access the DB on Android you need to have your class extend SQLLiteOpenHelper, now lets walk through the code required

private static String DB_PATH = "/data/data/com.tmm.android.chuck/databases/";
private static String DB_NAME = "questionsDb";
private SQLiteDatabase myDataBase; 
private final Context myContext;

First of all we define some simple class member variables. The DB_PATH will be used later to access our file that contains all our questions in it, the DB_NAME is just a name of choice to reference the DB.

public DBHelper(Context context) {
 super(context, DB_NAME, null, 1);
 this.myContext = context;
} 

You have to make sure you override the constructor, as this needs to initialise the context and DB before starting.

Next we have the createDatabase method – this one is quite straight forward:

public void createDataBase() throws IOException{

 boolean dbExist = checkDataBase();
 if(!dbExist)
 {
  this.getReadableDatabase();
  try {
   copyDataBase(); 
  } catch (IOException e) {
   throw new Error("Error copying database");
  }
 }
}


As you can see, it simply checks if the DB already exists, if it doesn’t (in which case its the first time that the app has been launched on this device) then it calls the copyDataBase() method:

private void copyDataBase() throws IOException{

 InputStream myInput = myContext.getAssets().open(DB_NAME);

 String outFileName = DB_PATH + DB_NAME;

 OutputStream myOutput = new FileOutputStream(outFileName);

 byte[] buffer = new byte[1024];
 int length;
 while ((length = myInput.read(buffer))>0){
  myOutput.write(buffer, 0, length);
 }

 //Close the streams
 myOutput.flush();
 myOutput.close();
 myInput.close();
}

Again, this is pretty straight forward – it just opens an Input stream to read the file (our questions file that we have saved in the /assets/ directory) and then writes it to the output stream which has been set up to be our DB Path/Name. Easy right?

So now we pretty much have our DBHelper class that checks for an existing DB, if its found then it opens a connection, if its not then it loads the data (our question set) in for the first time.

Now, the only remaining thing that our helper needs to do is to be able to access the data so we can select questions to show the user. So let’s look at how we add some DAO access methods. What I have done here is create a simple method to return a (random) question set:

public List getQuestionSet(int difficulty, int numQ){
 List questionSet = new ArrayList();

Cursor c = myDataBase.rawQuery("SELECT * FROM QUESTIONS WHERE DIFFICULTY=" + difficulty +
   " ORDER BY RANDOM() LIMIT " + numQ, null);
 
while (c.moveToNext()){
  Question q = new Question();
  q.setQuestion(c.getString(1));
  q.setAnswer(c.getString(2));
  q.setOption1(c.getString(3));
  q.setOption2(c.getString(4));
  q.setOption3(c.getString(5));
  q.setRating(difficulty);
  questionSet.add(q);
 }
 return questionSet;
}

Here, I am modelling the questions in a pre-created “Question” class – this just has the necessary member variables so I can handle the questions more easily than having to try and deal with DB cursors throughout the code. In the above method we just call a pure SQL statement, and then iterate through the cursor to populate my Question ArrayList.

And thats it! There are some other Activity classes and helper classes running doing small things throughout the app, but the core features are covered, so feel free to have a look around the code, edit it, change the design and just generally have fun.

43 comments:

Getting Started - A Complete Android App walkthrough for Beginners (Part 1)

About a year ago I released my first app on to the Android market. I had developed the market primarily as a learning tool, and at the end decided that putting it on the market would be a good step to understand the process and get some feedback.
The application was a simple quiz app based on the popular NBC series Chuck, I released it for free (no-ads) and no real advertising other than one or two target tweets. The app currently has about 4,000 – 5,000 downloads with a 4 star rating – both of which it achieved pretty quickly in the first month or two.



DISCLAIMER: I believe this to be purely down to the fact that at the time there weren’t really any other Chuck related apps, and it has a nerd-ish, cult like following, so I think the rating and popularity is more of a reflection on the show’s popularity than the quality of the app!


Anyway, I thought it might be interesting/helpful to release the source code here and walkthrough the different aspects of the code in a tutorial “my first app” kind of way.

I won’t go in to the setting up Eclipse/Android plug-ins stuff here, so will assume familiarity with getting around the IDE.


Android Directory Structure
Creating a new Android project in Eclipse (using the Android plug-ins) creates the required project structure automatically for you. Lets have a look at that now:


Src : as you would expect, this is the main java source directory, so this is where all your source code lives

Gen: this is the generated code that Eclipse handles for you – the files in here will be generated from your config. You needn’t really worry about what happens in here as Eclipse takes care of it for you

Assets: this can be used to contain any resources or libraries you want to bundle with the app – such as third party jars and data sets (you will see later we use this directory to store the data that we will load to populate all the questions in the DB when the app is first launched on a new device)

Res: this is where the configuration for the layout/UI aspects live:
- Drawable – keep you image files in here (.png/jpg/etc)
- Layout – this is where you keep the xml config for UI layout
- Values – this is where you keep the config with application code, such as application name or set text. This means you can easily change text through out the application without having to change hardcoded strings in the java code and re-compile


Getting Started
Ok, lets get started – the first thing we need is a welcome screen that is displayed when a user first launches the app. In Android, a screen is modelled by an “Activity” class, so to create our welcome screen we need to extend Activity.

public class SplashActivity extends Activity implements OnClickListener{

 @Override
 public void onCreate(Bundle savedInstanceState) {

Every class that overrides the Activity class must implement the onCreate() method – this is called when the activity is launched. As our welcome screen will just be a simple screen with a few buttons on it (play, rules, exit) we don’t need to do much at this point other than set up the buttons to have a listener so we know when one of them is pressed. For convenience here, we will set our current activity class to implement “OnClickListener” – this means we can define the onClick() method directly in our activity to handle the button events.

@Override
 public void onClick(View v) {
  Intent i; 
  switch (v.getId()){
  case R.id.playBtn :
   List questions = getQuestionSetFromDb();

   GamePlay c = new GamePlay();
   c.setQuestions(questions);
   c.setNumRounds(getNumQuestions());
   ((ChuckApplication)getApplication()).setCurrentGame(c);  

   //Start Game Now.. //
   i = new Intent(this, QuestionActivity.class);
   startActivityForResult(i, Constants.PLAYBUTTON);
   break;
   
  case R.id.rulesBtn :
   i = new Intent(this, RulesActivity.class);
   startActivityForResult(i, Constants.RULESBUTTON);
   break;
   
  case R.id.settingsBtn :
   i = new Intent(this, SettingsActivity.class);
   startActivityForResult(i, Constants.SETTINGSBUTTON);
   break;
   
  case R.id.exitBtn :
   finish();
   break;
  }
 }

As you can see, we have one single method that handles any button press, and we manage this with a switch statement checking the id of the view (we will go into this later). Mostly, the cases are simple, “exit” finishes the application whilst “rules” and “settings” have code like this:

i = new Intent(this, RulesActivity.class);
startActivityForResult(i, Constants.RULESBUTTON);

Intents are objects in Android that are used to communicate between activities, and as you can probably spot from the above, this simply creates a new Intent and then uses it to start another Activity class, in this case, our RulesActivity class.

The “Play” case is slightly more complicated – as this needs to initialise the game and load the questions to be used from the DB. Once it has done this, it loads the information in to our “Application” class (we will cover this later also) and then just kicks of the QuestionsActivity with a new Intent as per above.

So that is our welcome page pretty much done, we have a single screen that has a few buttons and we have setup listeners to perform appropriate actions on pressing them. The only remaining issue is the layout of the screen.


Activity Design

In the onCreate() method of our Activity you will notice the second line is

setContentView(R.layout.welcome);

This call tells Android which layout xml file should be used to configure the design – to find the relevant file is quite intuitive, its simply going to be located at /layout/welcome.xml



There are several layouts available to use, each of which are applicable in different circumstances, but as we are just going to have a straight list of buttons, we will use the simple “LinearLayout”. You can nest layouts, as you will see in this example, but lets walk through some of the config options we are using for our layout:

android:orientation="vertical" – This defines our layout as vertical, so new elements will be added on a new row below (if it were horizontal it would add as a new column)

android:layout_width="fill_parent" – this tells the activity to fill the whole width of the screen with the contents

android:layout_height="fill_parent" – this tells the activity to fill the whole width of the screen with the contents

android:gravity="center_horizontal" – this centers all elements that are contained in this layout

android:background="@drawable/background – this defines a background image to use for the activity (this image should exist at /drawable/background.png)


Now, if we look inside the layout you will see some simple components. The first one being a simple ImageView, which points to an image that we want to use as a header. The following elements are the buttons – you will notice that the ID of each button corresponds to the onCreate() method of our Activity where we inflate the button to set the onClickListener.
If you press the “Graphical Layout” tab in eclipse, you will see what the welcome screen will look like.




Ok, so we have our welcome Activty, we have designed a nice UI to control the app and have an onClick handler - the next part will cover intergrating with the DB to pull out the questions and then we are all there!


Grab complete source code for the project here

38 comments: