Mark Needham

Thoughts on Software Development

Archive for the ‘iPad’ Category

iPad: Getting PragProg books onto the Kindle App

with 5 comments

As I’ve mentioned previously I think the Kindle application on the iPad is the best one for reading books and as a result of that I wanted to be able to read some books which I’d bought from the PragProg store onto it.

The first step is to download the ‘.mobi’ version of the book and use iPhoneExplorer to drag the file into the ‘Kindle/Documents/eBook’ folder on the iPad.

This works fine but if you add more than one book in this way they all have the same cover image when viewed on the iPad which is quite annoying when trying to work out which book is which.

I went on a yak shaving mission to try and figure out how to solve that problem and came across a post by GRiker where he described how to set a custom cover image.

His instructions were as follows:

For example, let’s say you want to sideload WarOfTheWorlds.MOBI with its cover WarOfTheWorlds.JPG into the Kindle for iPad app:

  • Modify WarOfTheWorlds.MOBI (using Mobi2Mobi, for example), adding or modifying the ASIN field (in the EXTH block) with the name of the cover jpg, WarOfTheWorlds.JPG. (Since your sideloaded book didn’t come from Amazon, you don’t need a real ASIN.)
  • Copy the modified WarOfTheWorlds.MOBI to Kindle/Documents/eBooks (using iPhone Explorer)
  • Copy WarOfTheWorlds.JPG to Kindle/Documents/LibraryCovers (using iPhone Explorer)

I first loaded the mobi files into Calibre so that I could get the cover image by doing the following:

  • Click on the icon in the top left hand corner which looks like a book with a + sign on it
  • Add books from a single directory
  • Find the .mobi file you want to import
  • Right click on the book
  • Open containing folder

After I’d done that I needed to install ‘mobi2mobi’ in order to update the ‘ASIN’ number of the book. The Kindle application looks for a file with the same name as the ASIN number in the ‘LibraryCovers’ folder and uses that as the cover image for the book.

There are a crazy number of instructions to follow on the mobileread wiki in order to install this.

I followed these but was getting the following error when I tried to run the command:

Can't locate GD.pm in @INC (@INC contains: /Users/mneedham/eBooks/tools /Library/Perl/Updates/5.10.0/darwin-thread-multi-2level /Library/Perl/Updates/5.10.0 /System/Library/Perl/5.10.0/darwin-thread-multi-2level /System/Library/Perl/5.10.0 /Library/Perl/5.10.0/darwin-thread-multi-2level /Library/Perl/5.10.0 /Network/Library/Perl/5.10.0/darwin-thread-multi-2level /Network/Library/Perl/5.10.0 /Network/Library/Perl /System/Library/Perl/Extras/5.10.0/darwin-thread-multi-2level /System/Library/Perl/Extras/5.10.0 .) at /Users/mneedham/eBooks/tools/MobiPerl/Util.pm line 23.
BEGIN failed--compilation aborted at /Users/mneedham/eBooks/tools/MobiPerl/Util.pm line 23.

I came across the following thread where pilotbob described a way to fix this:

I got it working on Snow Leopard. Here is what I did.

1. Install MacPorts… this will make it a whole lot easier. http://www.macports.org

2. Once you get ports installed use macports to install the gd lib stuff:
sudo port install gd2

This will also install perl 5.8.9… perl 5.10 comes with Snow Leopard. Not sure it any mac stuff requires that… but you can always go back, macports puts stuff in a separate location.

I also installed the following macports:

p5-gd
p5-palm
p5-timedate
p5-getopt-mixed
p5-image-size
p5-xml-parser-lite-tree
p5-encode

Then, I use CPAN to install the following… there didn’t seem to be any macports for them:

HTML::TreeBuilder
Image::BMP

After that mobi2mobi ran… well it gave me the command line options. I didn’t actually try it. But, it doesn’t seem to run unless all the dependencies are there.

I tried to install all of those dependencies as he suggests although not all of them worked for me.

After I’d done that I went back to the mobileread wiki and re-ran the following commands:

sudo perl -MCPAN -e shell
 
install Palm::PDB
install XML::Parser::Lite::Tree
install GD
install Image::BMP
install Image::Size
 
install HTML::TreeBuilder
install Getopt::Mixed
install Date::Parse
install Date::Format

And after all that I was finally able to run ‘mobi2mobi’ to change the ‘ASIN’ of the file which can be done by executing the following command:

mobi2mobi my.mobi --outfile my.mobi --exthtype asin --exthdata "mycoverimage.jpg"

To get the Kindle application to pick up the new image I needed to be connected to the internet for some reason but all my books are showing with the correct covers now.

Written by Mark Needham

August 16th, 2010 at 7:18 am

Posted in iPad

Tagged with

iPad: Redrawing the screen

with one comment

As I mentioned in a post I wrote last week I’ve been writing a little iPad application to parse a cctray feed and then display the status of the various builds on the screen.

The way I’ve been doing this is by dynamically adding labels to the view and colouring the background of those labels red or green depending on the build status.

FirstViewController.h

@interface FirstViewController : UIViewController {
	...
	NSMutableArray *dynamicallyAddedFields;
}

FirstViewController.m

@implementation FirstViewController
 
- (void)viewDidLoad {
	...
	// parse xml and put projects into 'theDelegate.projects
 
	NSInteger x = 30;
	NSInteger y = 0;
	NSInteger column1 = true;
 
	dynamicallyAddedFields = [[NSMutableArray alloc] init];
 
	for(Project *project in theDelegate.projects) {		
		if(column1) {
			x = 30;
			y = y + 110;
			column1 = false;
		} else {
			x = 290;
			column1 = true;
		}
 
		UILabel *aLabel	= [self createLabelFrom:project withXCoordinate:x withYCoordinate:y];
 
		[dynamicallyAddedFields addObject:aLabel];
		[self.view addSubview:aLabel];	
	}
}
-(UILabel*) createLabelFrom:(Project *)project withXCoordinate:(NSInteger)x withYCoordinate:(NSInteger)y  {
	// code to create a label
}

The full code is on github and this is what the application looks like when launched in the simulator:

ipad.jpg

I’m storing each of the labels inside ‘dynamicallyAddedFields’ so that I can easily remove them and then redraw new ones with the new feed url when the user clicks on the ‘Go’ button. I saw a similar idea suggested in an iPhone Dev SDK article.

The ‘Touch Up Inside’ event of the ‘Go’ button is hooked up to the ‘changedFeedUrl’ method inside my view controller as described in Brandon Treb’s blog.

The code to handle the button being pressed is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- (IBAction) changedFeedUrl:(id) sender {		
	for (id item in dynamicallyAddedFields) {
		[item removeFromSuperview];
	}
	[dynamicallyAddedFields removeAllObjects];	
 
	// parse xml and put projects into 'theDelegate.projects
 
	NSInteger x = 30;
	NSInteger y = 0;
	NSInteger column1 = true;
	for(Project *project in theDelegate.projects) {		
		if(column1) {
			x = 30;
			y = y + 110;
			column1 = false;
		} else {
			x = 290;
			column1 = true;
		}
 
		UILabel *aLabel	= [self createLabelFrom:project withXCoordinate:x withYCoordinate:y];
		[dynamicallyAddedFields addObject:aLabel];
		[self.view addSubview: aLabel];
 
	}	
}

In order to redraw all the labels I had to first remove them all from their super view (line 3).

We then have the same code as in the ‘loadView’ method – copy and pasted for now – to add the new labels to the screen.

Although this code does what I want it is very hacky so I’d be grateful for any tips on how I can achieve the same thing in a cleaner way.

Written by Mark Needham

August 9th, 2010 at 4:38 am

Posted in iPad

Tagged with