Goodreads Developers discussion
examples / showcase
>
GoodReads Android App


Oauth is required, for security.

Is there any documentation for all of the response possibilities from the API? The API page gives a great description of all the requests and request options, but I didn't see anything on the responses. I want to be sure that I am covering all potential cases (for instance, all possible object types in an update element).





There is a competing Goodreads app for android on my phone...could that be causing the problem? The apk is completely different, but does the app name have to be unique?

There is a competing Goodreads app for android on my phone......"
That's a great question. I'll check the docs to see if it might cause issues, but I suspect since the package names are different (mine is com.onesadjam.GoodReads), they should not conflict.
I updated the apk on the project site. You may need to hit menu and logon/logout if you don't get prompted to authorize the app right away.

Fixed the manifest to allow installation on 1.5 and later. I setup a virtual device running 1.6 and it installed. Let me know if this still gives you an error.
Thanks!

"Application not installed: GoodReads could not be installed on this phone."
Wish I could guess what the problem was.

"Application not installed: GoodReads could not be installed on this phone."
Wish I could guess what the problem was."
Hmm, sorry for the frustration.
The app requires
- SD Card Access
- Sense Phone State
- Internet Access
In the phone application settings you must enable installation from unknown sources.
What is the other GoodReads app you have installed? I can try installing that on the emulator and see if I get a conflict as well.

The other app can be found at http://github.com/caspergasper/Gready...

I'm stumped. I can install in the emulator without issue, regardless of whether Casper's (very nice) app is installed or not. I uploaded a new apk that is targeted at 1.6 and is marked to handle various screen densities. It is a shot in the dark, but maybe this will help?

http://code.google.com/p/yagrac/
If you have installed the previous version, please uninstall it prior to installing this one.


That's great news! I'm still curious what it was that caused it not to install (possibly screen density issues?) but I'm glad it is working now.

Searching for either GoodReads or YAGRAC will find it.

Offical capitalization is "Goodreads" not "GoodReads" or "goodreads".
It took me a year an a half of working here to get this right.

Offical capitalization is "Goodreads" not "GoodReads" or "goodreads".
It took me a year an a half of working here to get this right."
Wow, I never knew! Thanks for the tip, Michael, I will update the text in my app to match that casing.

However, I'm going to need to use both until YAGRAC can use barcode scanning to add books to shelves more simply (just using ZXing is fine), which is what I'd tell folks when they ask me about GR & Android: Get both.
I'll put together some specs on how I would think it would work, and use case scenarios that'd be helpful over on your Issues Tracker.

However, I'm going to need to use both until YAGRAC ca..."
Thanks! I'll keep on eye on the issues board for those items. I'd really like to be able to integrate with Google Goggles, but I don't think there are published intents for that app.

Any idea why it won't let me authorize?


I also tried clearing my browser cache, but that didn't help. I even considered manually trying to delete any user data but couldn't figure out where it was hidden.
I'll uninstall/install again and see if that works.


On startup, YAGRAC reads from the applications preferences a few strings: user ID, token, and token secret. It then checks the value of token to see if it is empty or zero-length. If this is the case, rather than displaying the home screen, it immediately displays the Login screen. On the login screen, when you click Login it launches the browser to the Goodreads oauth page. When you click to allow the app access, the browser then fires an intent which the Login screen receives with the valid oauth access token and token secret. Next, the login screen attempts to retrieve your user ID using the token and token secret it just received. I think this is where the app is hitting a snag. For some reason, the request to get your user ID is failing, but it already retrieved a token and token secret.
Out of curiousity, when you get to the Goodreads oauth page, what happens if you deny the application access? I wonder if there is some combination of Logon / Logoff / Allow / Deny that will get you running again. I realize I'm grasping at straws, I'll post again if I can think of something that might help.

authorize=0 for fail
authorize=1 for pass
you may want to use the callback.

I tried denying out of curiosity this afternoon to see if that would somehow clear out something and I think it just put me into a loop where it kept trying to reauthorize again.
I also tried clearing the cookies and that didn't work either (didn't seem very likely, but you never know).

I've added a beta installer to the list of downloads. This won't resolve your issue, but it will give a slightly different error message that will help me in determining where things are going wrong.

@adam : what are using to implement the oauth spec?

@adam : what are using to implement the oauth spec?"
I am using the signpost oauth library
for android. I am using a version with a fix for POST parameter signing that Casper recommended. Not_Michael is the only case of this issue I have had reported, and unfortunately I am not able to reproduce it.


I posted a beta installer for YAGRAC on the project download page. Could you give this a try and note the specific error message? I've added some text here to allow for differentiating between the different types of oauth error cases. I appreciate your help with getting this solved.

I saw someone in the office fail to authenticate today with your app so it's not just Michael.
I haven't checked your code but I'm going to guess you're not storing the authorizationToken and authorizationTokenSecret before going to the Goodreads site? On some lower-end devices the app gets garbage collected whilst waiting for the callback so you need to recreate the provider with the authorizationToken and authorizationTokenSecret.
Casper.

public class LoginActivity extends Activity
{
private final static String _ConsumerKey = "myConsumerKey";
private final static String _ConsumerSecret = "myConsumerSecret";
private final static String _CallbackUrl = "onesadjam://goodreads";
private final static CommonsHttpOAuthConsumer _Consumer = new CommonsHttpOAuthConsumer(_ConsumerKey, _ConsumerSecret);
private final static OAuthProvider _Provider = new DefaultOAuthProvider(
"http://www.goodreads.com/oauth/reques...",
"http://www.goodreads.com/oauth/access...",
"http://www.goodreads.com/oauth/author...
onClick function for the login button:
String authUrl = _Provider.retrieveRequestToken(_Consumer, _CallbackUrl);
Context context = v.getContext();
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)));
onResume method
Uri uri = this.getIntent().getData();
if (uri != null && uri.toString().startsWith(_CallbackUrl))
{
String oauthToken = uri.getQueryParameter(OAuth.OAUTH_TOKEN);
// this will populate token and token_secret in consumer
try
{
_Provider.retrieveAccessToken(_Consumer, oauthToken);
}
I ran into trouble when I first started the app for precisely the reason you describe. My activity got garbage collected while the browser was active, and when re-created in response my instance variables were no longer initialized. I switched them to static members and the issue was resolved. That may not be the appropriate approach. I also played around with setting my activity to different instancing types (e.g. single top) but that did not seem to have the desired affect.


Casper.

I didn't even consider that my entire app was getting garbage collected. So when the browser window comes up my app doesn't just get paused, it is getting destroyed. It is restarted by the intent from the browser. The newly started app moves immediately to the LoginActivity which (and this boggles my mind since the _Consumer and _Provider are both instantiated via the static constructors) are no longer properly initialized!
@Casper - thank you very much for giving me a way to recreate this issue.
@This_Is_Not_The_Michael_You_Are_Looking_For - I'll get this fixed ASAP and let you know when it is ready.

@This_Is_Not_The_Michael_You_Are_Looking_For - I've posted a new beta download for you to try that includes the fix Casper recommended. Based on his tip, I was able to recreate the bug exactly as you describe. After changing the code, I can no longer repeat the issue. Please let me know if this allows you to authenticate.
http://code.google.com/p/goodreads/
It is very rough around the edges, but I'm eager to hear what folks would like to see in a client. I'm also curious as to what would qualify as a commercial effort with regards to the terms of service for the API (i.e. if I added an ad bar at the bottom, would it be considered commercial?).
Some features I hope to add soon:
- Post an update.
- Add / Move books on shelves
- Rate a book
- Review a book.
Any and all feedback is appreciated.
Thanks!