Twitter & other API's

Twitter has been added to the (now massive) list of API's that Bookfriend uses. What was interesting about the Twitter API was that it did not search for phrases, and instead searched for any combination of the words provided. This could be fine if I was looking for an author with an unusual name such as Jasper Fforde but not so good when searching for a book like 'Lost in a good book'. Therefore I initially search for the book name plus the author name, then the author name, and finally the book name. If enough results are found using the first technique then it does not look for any more. So in summary it looks for the most specific first before searching less specific phrases.

Here is a diagram explaining the API's vs. Functions

Bookfriend_2

Update to bookfriend

I have added radio buttons to allow search by author, book, ISBN. Originally it was a free text entry and worked reasonably well. Searching for 'Jasper Fforde' worked ok, but searches like 'Jane Austen' would find books called Jane Austen rather than books authored by her. 

Also I have added the ISBN API to the app, which allows exploration of categories and other books by the publisher.

The author gallery still needs work, and I need to load in images to the map screens. I have changed the icons on the map screens though as I mentioned in a previous post. 

Finally I now have the ability for the users to view different book summaries and select their favourite from them. 

Always pays to ask...

In the last week I've added the API from ISBNDB to my app and I've so far found it very easy to use and has some interesting information for a mashup, such as publisher location and other books. It also has searchable genres so I can find other books of the same genre. It seems to take longer to connect than some other API's, but the main issue I was having was that the 500 requests per day was far too little at this time as I am testing and developing new functionality.

So I e-mailed the developers, and within 24 hours, I had been granted an extra 1000 calls a day. Problem solved.

A while ago I was given full access to the Goodreads API as well. 

Map overlay issue

I was having a problem on both of the map views used in the app where the overlays would not display until the screen was touched. After looking on stack overflow I found that the problem was the overlays were being added once the zoom level had been set, which causes problems as Android doesn't know where to draw the overlays until the screen is touched, thereby moving the map and finding the zoom level.

I have changed the map overlay icons to some I found on the google wiki.

http://code.google.com/p/google-maps-icons/

Alpha release

My self-imposed deadline for releasing the first version to the general public has passed and I am desperate to get it out, so although it is far from feature complete I think it is stable enough to start getting people to have a look at it.

There are several features which I know are unfinished:

  1. Recent books currently does not save to the local database, it just remains there for as long as your bookfriend app is not destroyed by Android. This may cause errors when re-loading the app but that is my biggest priority.
  2. Author page sometimes finds no information about an author - I need to get it to redirect to a page rather than showing loads of blank spaces.
  3. This author page is the most problematic one at the moment due to massive changes to allow for multiple authors
  4. Author images needs to do something, either will pop up in a large view or will redirect to a gallery with sliding images
  5. Book places - going to include Flickr images about these places
  6. Filtering reviews (by star rating etc)

There are also several items that I'm going to add over the next 3 weeks.

I have a survey set up on Survey Monkey which is available at http://www.surveymonkey.com/s/K77GJ8H for anyone that uses this alpha version of bookfriend.

Link to Android market : https://market.android.com/details?id=com.carriehall.android.BookFriend&feature=search_result

 

Implementing Levenshtein Distance

When a user searches for a book manually they can enter a book name,
author, or keyword such as ISBN. The app queries Google Books which
pulls back a list of books ranked by relevance. Google Books does not
use the same ranking algorithms (PageRank) as their normal search but
this ranking is working for me so far. For an interesting article
about the Books API ranking algorithm, see
http://www.theatlantic.com/technology/archive/2010/11/inside-the-google-books...


Loading a list of books can be time consuming, so I wanted the app to
be clever in the way it 'guesses' at what book the user is looking
for. If an ISBN is entered then only one result is found and thus it
is straight-forward to redirect to the appropriate page. Further to
this if the user entered 'eyre affair' the app should guess that it is
likely to mean 'The Eyre Affair'. I looked into several possible
approaches to do this fuzzy matching.

The first is by using Levenshtein Distance which is what is currently
being used. A Java implementation is available within the
apache.commons.lang package available at
http://commons.apache.org/lang/download_lang.cgi . Levenshtein
Distance measures the difference between two sequences and is defined
by the amount of changes required to transform one string to the
other. It is known to be inefficient for large strings but it is
estimated that string input will be short due to the limited space for
entering a keyword.

Another possible solution is to use n-grams to determine approximate
matching, although it may be the case that on shorter string inputs
this will be more difficult. For more information on n-grams read the
wikipedia page at http://en.wikipedia.org/wiki/N-gram

Google Analytics

As I get the app ready for release I've decided to include Google
Analytics so that I can see what pages are used the most in the app,
and it will also help me to log errors.

The following is from Google's website:

The Google Analytics for Mobile Apps SDKs provide an interface for
tracking activity within mobile apps and reporting that activity to
Google Analytics. For example you can use this SDK to calculate
visits, session length, bounce rate and unique visitors. Tracking
mobile applications has some structural variations from tracking
website pages.

This SDK uses a tracking model that is designed to track visitors to
traditional websites and interaction with widgets in traditional web
pages. For this reason, the terms used below reflect the conventional
website tracking model and are being mapped over to tracking mobile
applications. You should be familiar with Analytics tracking in order
to understand how this SDK works.
Use the mobile tracking SDK to track your phone applications with the
following Analytics interaction types:

Pageview Tracking
A pageview is a standard means to measure traffic volume to a
traditional website. Because mobile apps don't contain HTML pages, you
must decide when (and how often) to trigger a pageview request. Also,
since pageview requests are designed to report on directory
structures, you should provide descriptive names for the requests to
take advantage of page path naming in the Content reports in
Analytics. The names you choose will be populated in your Analytics
reports as page paths even though they are not actually HTML pages,
but you can use this to your advantage by structuring paths to provide
additional groupings for your calls.

Event Tracking
In Analytics, events are designed to track user interaction to web
page elements distinctly from pageview requests. You can use the Event
Tracking feature of Google Analytics to make additional calls that
will be reported in the Event Tracking section of the Analytics report
interface. Events are grouped using categories and may also use
per-event labels, which provides flexibility in reporting. For
example, a multimedia app could could have play/stop/pause actions for
its video category and assign a label for each video name. The Google
Analytics reports would then aggregate events for all events tagged
with the video category.

Custom Variables
Custom variables are name-value pair tags that you can insert in your
tracking code in order to refine Google Analytics tracking.

normalise()

(See previous post about Google Books API -
http://bookfriend.posterous.com/google-books-api )

When retrieving genres using the Bookmooch API and my Java project, it
worked as expected.

'The Eyre Affair' would find

  • Mystery & Thrillers 
  • Literary 
  • Science Fiction & Fantasy
  • etc

However when I used the same code within the Android app it was
splitting the genres at the ampersands and apostrophes

  • Mystery 
  • Thrillers
  • Literary 
  • Science Fiction
  • Fantasy 

I believe this may be a similar problem to the one I had when
retrieving a book description from the Google API. It was solved by
one line of code (as most massive and annoying problems usually are!)

docEle = dom.getDocumentElement( );
docEle.normalize( );

Major flaw in app and beta release

I managed somehow to totally overlook the fact that a book can have
multiple authors. During the early stages of the app I thought about
it but never bothered to implement it. So the app would just find the
first author and display that to the user. Luckily, because I have
kept separation between the GUI and the core code it meant to change
such a crucial part was actually quite easy.

At the moment I am tidying up the graphics and aim to have the first
beta released by the end of this weekend.

Evolving code....

I've made various architecture decisions over the course of this
project. First was the initial idea of using a Facade to wrap all of
the various API classes and provide a level of abstraction between the
interface and the serious code. This was quite an early decision as it
became apparent quite quickly that there is a lot of code involved
even with the most basic Android screen, and so I wanted to keep it as
simple as possible.

More information about the Facade pattern is available at Wikipedia

Media_httpuploadwikim_bdlfd

Before the Facade I was passing data between Activities (Screens) by
using Intents with Bundles, i.e. the ISBN would be passed as a string.
Once I needed to pass more complex data I created a 'Book' object
which would be populated from all the various data sources. However
passing round this complex object was near to impossible and as I
needed it on all pages I also moved the Book object into the Facade
class, meaning that I can now access the Book object from anywhere
with very little code.

As more information has been added there have been more objects in the
Facade, such as Author and PhotoGallery. Author is a complex object as
it contains a variety of information and it is not contained within a
Book so that if a user selects books from the same author then the app
will be able to keep the same data.

Whilst I was reviewing the code within the Facade I realised that I am
making API calls and passing in various data as parameters. This is
less flexible and might cause problems in future developments. As I've
mentioned, all the data is available from the Facade so a single link
from the API to the Facade is all that is needed.

So I'm learning to constantly check the reasons why I've decided
something, as it often is just old code that is totally useless.