Tech: Building an RSS reader for Android (RIP Google Reader)

This tutorial will walk through building an RSS reader on the Android platform (focusing on 3.0 + as it will be using Fragments). All the code is available as a complete, working Android app that you can fork/download and fire up straight away on a compatible Android device/emulator. So feel free to go grab that from GitHub before continuing.

It is not an unusual requirement for mobile apps these days to be able to consume an RSS feed from another site (or many) to aggregate the content -  Or maybe you just want to build your own Android app now that Google has announced it will be retiring Reader.

Those of you who have worked with RSS in other JVM languages will know that there are plenty of libraries available that can handle parsing RSS - however, because the android platform doesn't actually contain all the core java classes, almost all of the RSS libraries have not been supported.

Fear not though, as Java's SAX parser is available, so with a bit of code we can get a custom RSS parser up and running in no time!

This walk through will cover off the basics of getting an RSS reader app up and running quickly and will also cover some details of Android's fragment system for tablet optimization as well as some things to watch out for (such as changes in the platform that mean network operations cannot be run in the main thread, which requires some tweaking if you have worked on earlier versions).

All the code for the app is also available on our GitHub so feel free to fork that and try loading it up on your Android device/emulator.

Parsing an RSS Feed:


So to get started we will look at parsing the feed - if you have any experience parsing XML using SAX in Java then you will know how easy this is. All we need to do is to tell the parser which XML nodes we care about, and what to do with them.

If  you have never implemented a SAX parser before, there are three primary methods that we will override: 
  • startElement() - This is called by the parser every time a new XML node is found
  • endElement() - This is called by the parser every time an XML node is closed (e.g. </.. )
  • chars() - this is called when characters are found between nodes



Because we only really care about capturing data from the leaf nodes, our startElement() method is left empty. The chars() element has to be watched, as there is no guarantee when it will be called (e.g. in a node like hello world  this method might be called several times between the start and end) so every time we will just append the contents to a StringBuffer - that way we can be sure that we will have captured all the data in the node.  By the time the endElement() method is called, we know that we have the contents of the node itself, and we just have to store the data.  At this point, we just quickly knocked up a POJO with the attributes that we wanted to capture - the Strings that we match on are the node names from the ATOM RSS feed (that Blogger uses) - if you are using another feed, just have a quick look at the feed and update the node names appropriately.

Using our Feed in an Android App

So, that was easy right? Once that parser has run through (and you could use that code standalone in any java app really) then you will have a list of Java objects that have the core details about the latest blog posts on the feed (title, author, datecreated, content, etc) - So now lets look at using it in an Android app.

We will assume a basic understanding of the Android SDK and the concept of Fragments, so won't go back to basics with that stuff.

What we will do, is create a basic ListFragment and an RSSService class that we will use to populate the list. In our ListFragment we will simply tell our RSS service to populate the list:



Simple right?

Let's take a look at what our helpful RSS service is doing for us.



The first thing to note is that this class is extending Android's AsyncTask- The reason for this is that since Android 3.0, you are no longer able to perform network operations in the main application thread, so being as our class is going to have to fetch some RSS feeds we are going to have to spin off a new thread.

As you can see, the constructor just sets some context info that we will use later on, and then builds a progress dialogue - this is then displayed in the onPreExecute() method - This lets us show a "loading" spinning disk whilst we fetch the data.

Android's AsyncTask's primary method that handles the actual work that you want to do asynchronously is called "doInBackground()" - In our case, this is simple - we just invoke our SAX RSS parser and fetch our feed data:



Finally, we will override the "onPostExecute()" method of the async class to use our newly fetched list to populate our ListFragment.  You note how when we overrode the doInBackground() method earlier we set the return to List of Articles (where Article is my simple POJO containing my RSS blog post info) - well this must correspond to the argument of the "onPostExecute()" method, which looks like this:



Actually, all we really needed to do in this method would be pass our new List or articles to the ListFragment and notify it of the change as below:



However, in our application we have added a bit more sugar on the app - and we have actually backed the app with a simple DB that records the unique IDs of the posts and tracks whether or not they have been read to provide a nicer highlighting of listed blog posts.

So that's it - there's plenty more you can add to your RSS reader app, such as storing posts for reading later, and supporting multiple feeds/feed types - but feel free to fork the code on GitHub, or just download on to your android device to enjoy all our NerdAbility updates!

Application running in Andriod emulator
RSS application running in an Andriod  tablet emulator




Spring security & subdomains

As previously mentioned, I have been working with a Spring MVC app that has had to deal with multiple subdomains for the one app (in other words, the subdomain really needs to just be considered as part of the normal URL path in all routing/security configuration and concerns).

Having gone through the details on how to make the @Controller and @RequestMapping routing to play nicely with subdomains, here is a quick overview of how to handle subdomains in Spring security.


A custom matcher

The main thing we really need to handle with security, is how to configure Spring-security so we can define permissions for URLs that include the subdomain.

Normally, Spring MVC permissions looks something like this:

As you can see, this just specifies a URL path to authenticate.


The specific details of how you implement the matcher exactly will be dependent on your applications approach to identifying and extracting the subdomain (maybe from http request, maybe just use a regex on the request etc)

As you can see above, the matcher we have created is just a convenient wrapper around another two spring matchers to let you match easily on both the full URL and subdomain.

Now, with a little convenience method, we can make some pretty nice Spring security configuration:

As you can see, the subdomain makes a difference to the permissions and who should access the two /dashboard/ URLs in the different contexts, but with the above simple code, we can make some pretty convenient & readable configuration to take subdomains into account.

Google kill off Google TV (in favour of Android TV)



Following on from expectations on the TV front, Google have just announced that they are end-of-life-ing Google TV as Android TV is fully operational as part of Android 5.0 - expect they are working with some OEMs right now to start getting some interesting devices launched..



Technology, innovation and 2015

There has already been several people, much smarter than me, offering predictions for the next year (my favourite is Fred Wilson's look back at last year and look forward to the next) which you should probably read rather than mine, but here we are anyway, so lets go with a few thoughts on 2015 and onward..


Television

I have written about this for a while, and the battle for the living room will continue to rumble on. I'm not sure if we will start to see one or two winners fighting it out this year, but I can only see this area getting more interesting.  NetFlix, Amazon Instant, NowTV have established themselves as the more dominant on demand providers but that is only a part of the battle - there is still the problem of platform fragmentation (no common platform across devices/TVs/etc to run consistent experience apps - some devices not being able to support updating OD apps etc).  Android has a real opportunity to tackle this problem, given that pretty much all content providers already support the Android platform in smaller sizes, but let's see what they do. If they can become the defacto television/set-top box OS it would be a big win for them, but would also mean that device manufacturers & content providers don't need to worry about building & supporting their apps for a range of platforms and can focus on building the best experience on a single platform.

There is also the question as to the role of the actual TV device - will it be a smart device with a dedicated platform, or will it become dumber that just streams content from any other mobile device.


Enterprise

There has been some hype around Enterprise startups growing over the last 12 months, and this will also slowly increase - as has always been the way with enterprise, things have been very slow in terms of adoption and businesses and executive teams generally very wary about adopting new technologies until they are really widely adopted and proven - but this is starting to change. As more and more areas of business are starting to be disrupted by upcoming startups, more established businesses are starting to adopt technology more quickly to try and stay in the game, and more and more starting to spin off departments/teams from the business to operate as micro-startups to help drive innovation.  I think with this trend for bigger businesses becoming more willing to adopt new tech continuing, we will see some big noise in the enterprise/SaaS areas.


FinTech

Similar to wider enterprise trends, the banks and financial institutions are starting to become more aware of the risk and trends in their business with more and more people starting to expect better/different ways to do business.  From the larger tech of Bitcoin through to ApplePay, Square etc I think we will see continued innovation and surprises from the bigger players as well as a whole host of startups snapping at their heels.  With London currently the world FinTech capital it could be an interesting year here.


Education

This is an area I am interested in and have written about on a few occassions. I'm not sure this will really be a big area in 2015, there certainly aren'y any startups I am aware of that look like they might make really big waves in the year, but here's hoping.  Either way, there are still interesting things going on - there is the continued change in the UK curriculum with things like the "hour of code" and the continued drive to put more tech on the curriculum. Plus, I have recently spoken to two startups recently that are doing interesting things in the education mobile app space: Zzish and kahoot  - they are both working on mobile app/web platforms for the classroom with a bunch of tools to help teachers and children learn and work together.


The rest..

I agree with many of the other observations on Fred Wilson et al's writing - continued growth, acquisitions and big IPOs from the current crop of big startups will continue (AirBnB, Uber etc).

Companies like Xiaomi will continue to grow and hopefully come and start to be real contenders in the western markets (even if the Xiaomi laptops have been leaks, I'm still interested to see if they do come with a laptop anything like the leaked specs.. could get interesting!)

As Fred Wilson mentions, and as I have previously written, I don't think wearables are really ready to be a thing. Still more work needed on how these will fit into the market, and I don't think that will be happening in 2015.




Technical aptitude testing & recruiting

Having spent a reasonable amount of time on both sides of the interview table, plus having co-founded NerdAbility, it may come of little surprise that I am pretty opinionated on the topic.

It's a pretty divisive topic, and a lot of people feel quite strongly about a lot of this stuff, but here's my opinion anyway..


Tech tests

First up is the question of whether or not potential candidates should have to take some kind of tech test. Personally I like them. But with a few caveats:

  1. They should be easy. 
    This might sound counter intuitive, but I prefer a relatively simple tech test.  In reality, I'm not really convinced that you gain that much from the more complex tests, and at worst, probably just get false negatives and end up mistakenly ruling out great candidates.  I have seen tests that take days (unit testing/mocking/designing/coding/reviewing/re-factoring etc.) and if anything they put candidates off, and as mentioned probably don't provide much info.

    Something nice and simple, let's say a modest estimate of an hour all in is probably about right.  As ranted about by many folk, famously Jeff Atwood, a basic FizzBuzz programming test will rule out a lot of people.

    Further more, when I review test submissions I don't really care about if they work - what I am really looking at is the coding style and overall approach. Coding style, class structuring, use of nice libraries/core functionality/data structures, unit tests.  If you have a simple test that should take no more than an hour to code then candidates really don't have any excuse not to make their best efforts with how the code is structured, unit tested etc - so you can set the bar pretty high.
  2. They shouldn't be timed
    Timing the tests just blur the lines - if you are timing the tests then you have to lower the bar. With a simple, non-timed test, you can say you will rule out people who haven't submitted unit-tests for example, but if you set a time limit then you have to excuse people - and will inevitably find yourself saying things like

    "Well, sure its 200 lines of code all in the main() method, and variable names like 'tmpString', and it probably doesn't work, and it's not unit-tested.. but maybe they were rushed for time.. maybe we should bring them in..? "

    It happens, the bar slips lower and lower, and eventually the test is serving no purpose other than ruling out those people who just can't be bothered.
  3. They should be core technology concepts
    There is no point having tests that test specific domain knowledge or expect experience beyond core language competencies. Even if your business is in a very specific niche, you are going to do much better hiring great tech folk if you test core competencies rather than specific libraries/tools/technologies.
  4. They should be done before hand
    On-site testing adds a different dimension to the test - whether it be whiteboard or on a machine, there are other variables that can end up being a distraction. On a whiteboard candidates can end up worrying over exact method signatures and missing semi colons (but whiteboard is much preferable to actual coding - In my opinion, you should never expect a candidate to bring a laptop, and asking a candidate to use another machine/OS/IDE is also fraught with potential distractions).



What's the point?

As mentioned, I am not a big believer in using the tests to really measure if someone is a great programmer. For me, they serve two simple purposes (well three actually, but I will mention the third point later)
  1. They can be bothered. They are actually interested enough in the role and the company to invest their own time and energy. This will rule a few people out who are just machine gunning resumes out to lots of companies blindly, or those who are just after some interview practice.
  2. They have demonstrated an understanding of core technology approaches/patterns - Simple things like Single-responsibility, unit testing (use of good assertions, sensible testing, messaging etc), class organisation shows that they have actually spent a reasonable amount of time programming and keep up technology.  A nice little example of this, that I like to see, is use of Java's Collections/Arrays convenience methods (assuming testing Java!)  Arrays.asList( "1", "2", "3" ) makes declaration of explicit lists easier (nice for testing etc) and shows a knowledge of core Java stuff.


So all we have so far is know they can be bothered and that they have a good understanding/interest in program design/architecture - not much more that can indicate whether or not they are an awesome developer.



The interview

This is where the test really comes into its own.  I think using the test to drive the tech interview is really a great way to go.

You can walk through the code, ask about design decisions, and with a little extra thought you can easily push into variations of the test, how would they handle other constraints and you can continue to push through varying degrees of complexity, and if you are consistent with your tests you get a consistent sliding scale to compare candidates - you know exactly at what point did each candidate get to on the scale of questions. See this article as a great example of this technique more generally (also fun/good practice to try working through the problems the author is asking before reading the answers to see how far you get).

This approach of starting very easy and working up a sliding scale of difficulty is a common practice used by big co's like Google et al.



An example

Here's an approach I quite like

Tech test: the problem

Given a webpage address, find the most common word on the page.

This tests core technology concepts, stuff like good usage of HashMap (or similar) data structure for counting words, extensive enough to need some proper unit testing, but quick enough to complete relatively quickly.


Interview: followup

There are a few follow up questions that can be used to further probe the candidates understanding:
  1. What would you need to change if I wanted the most common word on a whole website (e.g. wikipedia) - this can go into how to crawl webpages and potential pitfalls if that is a relevant area, but otherwise can go into challenges regarding the amount of information needed to be stored, e.g. if you have limited memory, how can you store the info etc
  2. If I wanted the top 5 most common words how would you change it?  This is interesting as there are a variety of solutions, and unless they go straight for the optimal solution you can keep asking if they can think of any better solution. 

    For example, they might just keep track of the top 5 words during the counting, which is pretty efficient, but less flexible when top 5 becomes Top X words;

    Alternatively they may just count all the words, then implement a comparator for the Map entries and sort them all and just take the top X - which is flexible but is always going to be  O(nlogn) performance (sorting is always at best nlogn)

    Another approach is to use a Heap (PriorityQueue in Java), and heapify the counted set (heapify can be completed in O(n) time) then just take the top X elements from the queue (X being a lower order constant not dependent on the size of the dataset, and log n being lower order than the linear time to heapify the data upfront,  so performance is O(n))

    You can also follow up this question with further questioning about performance and Big-O - if thats something that you think is interesting/relevant for the position - which it might not be..



Whatever test you choose, as long as you have some sensible and interesting questions to follow up with, I think it makes for a pretty productive process and in many ways is optimized for the candidate making the best impression they can.

Spring MVC & custom routing conditions

I have recently been building a Spring MVC app (well, actually using the Spring Boot project - which is quite nice in parts, and crazy frustrating in others - but the underlying mechanics are the same).  The application is actually a re-build of another application, so it has involved a lot of playing and exploring Spring source code to try and replicate the apps functionality like for like.

One of the first things I found, was that Spring doesn't really cater for the concept of a single app running on different sub-domains.  I assume the thinking is that you would build separate applications for different sub-domains, but in this case, we just have a single app.

There are two main speed-bumps I have come across so far:
  1. Controller routing based on subdomain
  2. Security considerations based on subdomain

Basically, as you can probably imagine, once you have subdomains on a single web application, the URL path is no longer unique (e.g. http://automateddeveloper.blogspot.com/ is clearly not the same as http://blogspot.com/ )


The rest of this post, I will look at the routing element of it. I will do another post later in the week about the Spring security stuff (I haven't solved all of that yet - but got far enough to make it work).


Understanding the subdomain

The first thing you need to sort out is a common and consistent way to determine the subdomain of any given request. There are a variety of ways to do this, for example, you could parse it from the request in apache and set a header, so your app doesn't have to worry about it, or you could just parse it from the request object server name. I will assume you have some bean/service/helper class to do this everywhere (although for now we only need it in one place).


An annotation

First up, we need a new annotation, that we can easily apply to a Controller, just like we would use the @RequestMapping - at the moment, the nice built in Spring RequestMapping handling allows you to define a URL path (plus other bits and pieces) to map a request to a URL to a given controller & method - what we want is to also specify the subdomain element of the requested URL

Defining an annotation is simple:

For the sake of simplicity of this example, I will only allow it to be used at class level (so no method based subdomain routing - but that will be pretty easy to do once you have understood the rest of the post).  You will also note that the value is defined as a String array, this will allow us to define mappings to multiple subdomains if needed.


The mapping condition

So, that was easy. Obviously, at this point the annotation doesn't actually do anything - you can add it to all the controllers you like, but it won't actually make any difference to your request routing.

To get our new annotation involved, we can implement something called a RequestCondition.  This is exactly what it sounds like, Spring lets you implement additional request conditions that must be satisfied for a request mapping.

The condition could be based on any logic you like, but in our case we just simply need to check for an annotation and then examine the value provided.  If the annotation value matches our incoming request then the condition is met, easy!  Returning the condition indicates to Spring that the condition has been met, returning the null value indicates that the condition is not met.


Adding the condition to the mapping handler

Usually, we would use the standard Spring RequestMappingHandlerMapping to handle all the routing of requests based on the URLs, but now we need to also ask Spring to consider our new custom condition from above.

This is a simple case of extending the normal RequestMappingHandlerMapping class and adding our new condition as a custom condition.  Luckily, this is really easy:

Allwe are doing is checking to see if the handler class (our controller) has our new @Subdomain annotation and if it does, we register our new custom condition for consideration.



Basically..

That's really all there is to it - we can then decorate our controller class with @Subdomain("subdomain") and have them handle the routing of requests. 

As you may have noticed, this is a pretty nice pattern for any kind of custom routing you might want to use - the same template could be used for routing by any request info/header or any user info (e.g. routing requests to different controllers based on their logged in role etc)