Google Reader | Titanium Development

All posts in Google Reader

Appcelerator Titanium Mobile & the Google Reader API: Part 2

In Part 1 of this series, I showed you how to get authorized to the Google Reader API and get a list of feeds. In part 2, I’m going to show you a couple ways to get items.

The easiest way to get items is to make a request to the

/reader/api/0/stream/contents/user/-/state/com.google/reading-list

url. This will get the latest 20 items in your reading list.

var xhr = Ti.Network.createHTTPClient();
var url = "http://www.google.com/reader/api/0/stream/contents/user/-/state/com.google/reading-list?client=reader";
xhr.open("GET", url );
// set the cookie so google knows it is me
xhr.setRequestHeader("Authorization", cookie);
xhr.onload = function() {
  var response = JSON.parse(xhr.responseText);
  for( var i = 0; i < response.items.length ; i++ ){
    Ti.API.debug( response.items[i].title );
  }
};
xhr.send();

You can use parameters on the URL to exclude read items or change the number of returned items.

url += "&xt=user/-/state/com.google/read";  //exclude read items
url += "&n=100";  //get 100 items

This method is very fast, but can bring down a whole lot of data. I don’t know of any way with this method to ‘paginate’ your requests so you get the next 50 items for example. Because of these limitations, most iOS RSS readers use a different method.

The method most RSS readers on iOS use is to:

  1. get the ‘ids’ of all the items you want to retrieve, then;
  2. make multiple requests for the data for the items by id in batches of about 40 articles at a time.

Here is an example of getting the ids of the last 500 items:

xhr = Titanium.Network.createHTTPClient();
var url = "http://www.google.com/reader/api/0/stream/items/ids?n=500&output=json&s=user/-/state/com.google/reading-list";
xhr.open("GET" , url );
xhr.setRequestHeader(  "Authorization" , cookie );
xhr.onload = function(){
  var response = JSON.parse(this.responseText);
  for( var i = 0; i < response.itemRefs.length ; i++ ){
  	Ti.API.debug( response.itemRefs[i].id );
  }
  // stash these in a global variable for later use
  itemRefs = response.itemRefs;
};
xhr.send();

Now that you have the ids, you POST them back to the server to get the article contents. Here, I am getting the first 20 articles.

var xhr = Titanium.Network.createHTTPClient();
var url = "http://www.google.com/reader/api/0/stream/items/contents";
xhr.open( "POST" , url );
xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded');
var postData = "";
for( var i = 0; i < 20; i++ ){
  // pop the item cause I won't get it again 
  var item = itemRefs.pop();
  // keep adding i=XXXXXX
  postData += "&i=" + item.id;
}
xhr.setRequestHeader(  "Authorization" , cookie );
xhr.onload = function(){
  var response = JSON.parse( xhr.responseText );
  for( var i = 0; i < response.items.length ; i++ ){
  	Ti.API.debug( response.items[i].title );
  }
};
xhr.send(postData);

This method provides a nice way to add items over a period of time to lessen the wait for the user before seeing the first article. It has the added benefit of reducing the worry that your app will crash from getting too much data in a single request!

In Part 3, I’ll show you how to update the state (unread, starred, etc.) for items. Codestrong!

Date posted: October 14, 2011

0 Comments
Top

Appcelerator Titanium Mobile & the Google Reader API: Part 1

I saw a question on Twitter this week about using the Google Reader API with Titanium Mobile. I have done a ‘almost’ full integration with Google Reader in My Newspaper for iPad so thought I would give a run down.

I am standing on the sholders of giants here. I owe most the credit to Martin Doms and his AWESOME 3 part tutorial on accessing Google Reader. Go check them out. They give a better run-down of all the parts and concepts than I could ever give:

  1. Using the Google Reader API – Part 1
  2. Using the Google Reader API – Part 2
  3. Using the Google Reader API – Part 3

To access the Google Reader API, I use the Ti.Network.HttpClient. The first trick is getting authorized, Just make a ‘GET’ call to the ClientLogin url with your email and password as parameters:

	var xhr = Ti.Network.createHTTPClient();
	xhr.open('GET', "https://www.google.com/accounts/ClientLogin?service=reader&Email=" + email + "&Passwd=" + password);

When the http call returns, you need to get line with ‘Auth=’ in it and save that value. You’ll need to send it with any future requests that require authorization.

	xhr.onload = function() {
		if(xhr.status == "200") {
			var response = xhr.responseText.split("\n");
			for(var i = 0; i < response.length; i++) {
				var tokens = response[i].split("=");
				if(tokens[0] == "Auth") {
					alert( "login successful. token is " + tokens[1] );
					token = "GoogleLogin auth=" + tokens[1];
					button2.enabled = true;
				}
			}
		} else if(this.status == "403") {
			alert("invalid credentials for google reader");
		} else {
			alert("unexpected status from google reader: " + this.status);
		}
	};
	xhr.send();

Now that you have the token, you just need to set the ‘Authorization’ request header with the token when making a ‘secure’ request. Here I am getting the list of feeds I am subscribed to.

	var xhr = Ti.Network.createHTTPClient();
	var url = "http://www.google.com/reader/api/0/subscription/list?output=json";
	xhr.open("GET", url);
        // This is important
	xhr.setRequestHeader("Authorization", token);

You see I requested the output in JSON in the url which makes return data really easy to manipulate when loaded.

	xhr.onload = function() {
		var response = JSON.parse(xhr.responseText);
		// Do something with the subscriptions
		for(var i = 0; i < response.subscriptions.length; i++) {
			Ti.API.debug(response.subscriptions[i].title);
		}
	};
	xhr.send();

That is all for this post. Next time, I’ll talk about reading items and setting their status (unread, starred, etc).

Jeff

Appcelerator Titanium Mobile & the Google Reader API Part 2: Getting Items

Full working app to login and get feeds:

Titanium.UI.setBackgroundColor('#000');

var tabGroup = Titanium.UI.createTabGroup();

// Google Reader Authorization
var email = "mysecretemail@mydomain.com";
var password = "mysecretpassword";
var token = "";

var win1 = Titanium.UI.createWindow({
	title : 'Google Reader',
	backgroundColor : '#fff'
});
var tab1 = Titanium.UI.createTab({
	icon : 'KS_nav_views.png',
	title : 'Feeds',
	window : win1
});

// table to hold all the feeds
var table1 = Ti.UI.createTableView({
	top : 45
});

win1.add(table1);

var button1 = Ti.UI.createButton({
	title : 'login',
	height : 30,
	left : 5,
	width : 80,
	top : 5
});

button1.addEventListener('click', function() {
	// Login to Google Reader
	var xhr = Ti.Network.createHTTPClient();
	xhr.open('GET', "https://www.google.com/accounts/ClientLogin?service=reader&Email=" + email + "&Passwd=" + password);
	xhr.onload = function() {
		if(xhr.status == "200") {
			var response = xhr.responseText.split("\n");
			for(var i = 0; i < response.length; i++) {
				var tokens = response[i].split("=");
				if(tokens[0] == "Auth") {
					alert("login successful. token is " + tokens[1]);
					token = "GoogleLogin auth=" + tokens[1];
					button2.enabled = true;
				}
			}
		} else if(this.status == "403") {
			alert("invalid credentials for google reader");
		} else {
			alert("unexpected status from google reader: " + this.status);
		}
	};
	xhr.send();
});

win1.add(button1);

var button2 = Ti.UI.createButton({
	top : button1.top,
	height : button1.height,
	width : button1.width,
	left : button1.left + button1.width + 5,
	title : 'Get Feeds',
	enabled : false
});

button2.addEventListener('click', function() {
	// Get the Feeds to are subscribed to
	var xhr = Ti.Network.createHTTPClient();
	var url = "http://www.google.com/reader/api/0/subscription/list?output=json";
	xhr.open("GET", url);
	xhr.setRequestHeader("Authorization", token);
	xhr.onload = function() {
		var response = JSON.parse(xhr.responseText);
		// Do something with the subscriptions
		var data = [];
		for(var i = 0; i < response.subscriptions.length; i++) {
			data.push({
				title : response.subscriptions[i].title
			});
		}
		table1.setData(data);
	};
	xhr.send();

});

win1.add(button2);

var win2 = Titanium.UI.createWindow({
	title : 'Other',
	backgroundColor : '#fff'
});
var tab2 = Titanium.UI.createTab({
	icon : 'KS_nav_ui.png',
	title : 'Other',
	window : win2
});

tabGroup.addTab(tab1);
tabGroup.addTab(tab2);

// open tab group
tabGroup.open();

Date posted: October 5, 2011

3 comments - Latest by:
  • jeff Thanks for the heads up Stavros. That looks like a great resource to help with the google oauth2 stuff.
  • Stavros Kounis Hi, first things first this is a great article and helped me locate the right path. While digging I noticed ...
Top
Page 1 of 1