Archive for category iPhone Development

Evernote – Bible Notes Preview

I spent the day having fun with the Evernote API and these are some screenshots showing notes I was able to send from our BibleReader application. Hoping to have a beta out next week.

Showing two notes uploaded from within the BibleReader app.

Showing more detail on a single note uploaded from BibleReader - note the tags are used to keep track of catagory, verse reference, and icon.

Tags: ,

Evernote API Cocoa Example

Disappointed by the lack of Evernote love for the iPhone SDK I decided to port their python example to Cocoa. This code snippet should work with Cocoa and Cocoa Touch.

#import "EvernoteBackup.h"

#import "THTTPClient.h"
#import "TBinaryProtocol.h"
#import "UserStore.h"
#import "NoteStore.h"

@implementation EvernoteBackup

- (void)Test
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	// Keep this key private
	NSString *consumerKey = [[[NSString alloc] 
		initWithString: @"YOUR_CONSUMER_KEY_HERE" ] autorelease];
	NSString *consumerSecret = [[[NSString alloc] 
		initWithString: @"YOUR_CONSUMER_SECRET_HERE"] autorelease];
	// For testing we use the sandbox server.
	NSURL *userStoreUri = [[[NSURL alloc] 
		initWithString: @"https://sandbox.evernote.com/edam/user"] autorelease];
	NSString *noteStoreUriBase = [[[NSString alloc] 
		initWithString: @"http://sandbox.evernote.com/edam/note/"] autorelease];
	// These are for test purposes. At some point the user will provide his/her own.
	NSString *username = [[[NSString alloc] 
		initWithString: @"YOUR_USERNAME_HERE"] autorelease];
	NSString *password = [[[NSString alloc] 
		initWithString: @"YOUR_PASSWORD_HERE"] autorelease];

	THTTPClient *userStoreHttpClient = [[[THTTPClient alloc] 
		initWithURL:userStoreUri] autorelease];
	TBinaryProtocol *userStoreProtocol = [[[TBinaryProtocol alloc] 
		initWithTransport:userStoreHttpClient] autorelease];
	EDAMUserStoreClient *userStore = [[[EDAMUserStoreClient alloc] 
		initWithProtocol:userStoreProtocol] autorelease];
	EDAMNotebook* defaultNotebook = NULL;

	BOOL versionOk = [userStore checkVersion:@"Cocoa EDAMTest" :
						[EDAMUserStoreConstants EDAM_VERSION_MAJOR] :
						[EDAMUserStoreConstants EDAM_VERSION_MINOR]];

	if (versionOk == YES)
	{
		EDAMAuthenticationResult* authResult = 
			[userStore authenticate:username :password 
				:consumerKey :consumerSecret];
		EDAMUser *user = [authResult user];
		NSString *authToken = [authResult authenticationToken];
		NSLog(@"Authentication was successful for: %@", [user username]);
		NSLog(@"Authentication token: %@", authToken);

		NSURL *noteStoreUri =  [[[NSURL alloc] 
			initWithString:[NSString stringWithFormat:@"%@%@", 
				noteStoreUriBase, [user shardId]] ]autorelease];
		THTTPClient *noteStoreHttpClient = [[[THTTPClient alloc] 
			initWithURL:noteStoreUri] autorelease];
		TBinaryProtocol *noteStoreProtocol = [[[TBinaryProtocol alloc] 
			initWithTransport:noteStoreHttpClient] autorelease];
		EDAMNoteStoreClient *noteStore = [[[EDAMNoteStoreClient alloc] 
			initWithProtocol:noteStoreProtocol] autorelease];

		NSArray *notebooks = [[noteStore listNotebooks:authToken] autorelease];
		NSLog(@"Found %d notebooks", [notebooks count]);
		for (int i = 0; i < [notebooks count]; i++)
		{
			EDAMNotebook* notebook = (EDAMNotebook*)[notebooks objectAtIndex:i];
			if ([notebook defaultNotebook] == YES)
			{
				defaultNotebook = notebook;
			}
			NSLog(@" * %@", [notebook name]);
		}

		NSLog(@"Creating a new note in default notebook: %@", [defaultNotebook name]);

		// Skipping the image resource section...

		EDAMNote *note = [[[EDAMNote alloc] init] autorelease];
		[note setNotebookGuid:[defaultNotebook guid]];
		[note setTitle:@"Test note from Cocoa Test."];
		NSMutableString* contentString = [[[NSMutableString alloc] init] autorelease];
		[contentString setString:	@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"];
		[contentString appendString:@"<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml.dtd\">"];
		[contentString appendString:@"			<en-note>Here is the Olive Tree Test note.<br/>"];
		[contentString appendString:@"			</en-note>"];		
		[note setContent:contentString];
		[note setCreated:(long long)[[NSDate date] timeIntervalSince1970] * 1000];
		EDAMNote *createdNote = [noteStore createNote:authToken :note];
		if (createdNote != NULL)
		{
			NSLog(@"Created note: %@", [createdNote title]);
		}
	}

	[pool drain];
}

@end

Again your mileage may vary but I think this gives you the gist of how to talk to the Evernote servers.

Tags: , ,

Evernote API and iPhone SDK Setup

I was surprised by the lack of details on this topic so I decided to post my experiences with getting Evernote’s API setup in an iPhone application.

Note: Don’t forget to ask for an Evernote API key.

Steps for geting Evernote API compiling for the iPhone.

1. Grab thrift cocoa runtime:

  
$> svn co http://svn.apache.org/repos/asf/incubator/thrift/trunk/lib/cocoa/src/ thrift-cocoa

2. Grab latest Evernote API from http://www.evernote.com/about/developer/api

$> wget http://www.evernote.com/about/developer/api/evernote-api-1.xx.zip

3. Unzip Evernote API

$> unzip evernote-api-1.xx.zip

4. Go into the evernote cocoa source directory and replace every occurance of <Cocoa/Cocoa.h> with <UIKit/UIKit.h>

$> cd evernote-api-1.13/src/cocoa
$> perl -pi -e 's/<Cocoa\/Cocoa.h>/<UIKit\/UIKit.h>/g' *.h
$> perl -pi -e 's/<Cocoa\/Cocoa.h>/<UIKit\/UIKit.h>/g' *.m

5. Open XCode and add a ‘3rdParty’ group with the group “Evernote” beneath it

6. From the 3rdParty group click “Add existing files” and select the thrift-cocoa folder.

7. Expand the thrift-cocoa folder and delete the references to the folder server and everything contained within it.

8) Expand the transport folder and delete TSocketClient.m & TSocketClient.h (Evernote does not appear to need these and they won’t build with the iPhone SDK.)

9. From the “Evernote” group click “Add existing files” and select the cocoa folder under evernote-1.xx/src/cocoa

10. Try to build the system. I am using 1.13 and for whatever reason the cocoa is borked and needs some massaging. If you get errors like ‘EDAM_MIME_TYPES’ undeclared (first use in this function) then you have two choices. Install boost and thrift idl and run the thrift files in evernote-api-1.xx/src/thrift through thrift and it should generate good files otherwise you need to look at the errors and determine if you can fix them using some simple replacements as I have done below…

# Replaces the erroneous EDAM_ with EDAMEDAM_
$> perl -pi -e 's/ EDAM_/ EDAMEDAM_/g' EDAMLimits.m
$> perl -pi -e 's/ EDAM_/ EDAMEDAM_/g' Types.m
$> perl -pi -e 's/ EDAM_/ EDAMEDAM_/g' UserStore.m
# But this breaks the function definitions so I refix them here.
$> perl -pi -e 's/\+ \(int32_t\) EDAMEDAM_/\+ \(int32_t\) EDAM_/g' EDAMLimits.m
$> perl -pi -e 's/\+ \(NSString \*\) EDAMEDAM_/\+ \(NSString \*\) EDAM_/g' EDAMLimits.m
$> perl -pi -e 's/\+ \(NSSet \*\) EDAMEDAM_/\+ \(NSSet \*\) EDAM_/g' EDAMLimits.m
$> perl -pi -e 's/\+ \(NSString \*\) EDAMEDAM_/\+ \(NSString \*\) EDAM_/g' Types.m
$> perl -pi -e 's/\+ \(int16_t\) EDAMEDAM_/\+ \(int16_t\) EDAM_/g' UserStore.m

Your mileage will vary. 😉

Tags: , ,