grapi
grapi copied to clipboard
Goodreads unofficial android SDK ๐
good reads api
Since Goodreads retire their api, this project should be considered deprecated as well. ๐

Goodreads unofficial android SDK.
Features
SDK handles login via OAuth with access token storage management and allow you to make requests to goodreads api with no pain. All code written in modern Kotlin. ๐
Currently supported api methods:
Iโm currently adding the rest of the methods, so if you have feature requests or pull requests or just a comments - open an issue and I will try to help you. RFC.
Implementation details Medium Post
Setup
- Make sure you have the jitpack repo in your project level
build.gradle:
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
- Add the dependency to your app
build.gradle:
implementation 'com.github.intmainreturn00:grapi:1.4'
- Register your app at Goodreads
I recommend storing api key and secret at global gradle.properties file - this way you donโt risk accidentally post it to git and its a common practice. This file usually can be found at your user home directory. [about global properties]. This is the way I do it at sample app. (donโt mess it with local gradle.properties, which can be added to git)
- OAuth authorisation requires redirect, so you need to add this intent filter with your callback url, given from goodreads registration. (change host and scheme to your names - at sample app I used manifestPlaceholders for it)
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="${host}"
android:scheme="${scheme}"/>
</intent-filter>
Usage
Initialise before usage. (I donโt keep reference to context, just using it for shared prefs, so donโt be afraid of memory leaks)
grapi.init(this, BuildConfig.goodreadsKey, BuildConfig.goodreadsSecret, BuildConfig.goodreadsCallback)
OAuth:
Oauth flow:
- Call
loginStart(). - Redirect to url from
getAuthorizationUrl. - After user returns back,
loginEnd(intent)with given intent.
login.setOnClickListener {
if (!grapi.isLoggedIn()) {
launch {
grapi.loginStart()
browse(grapi.getAuthorizationUrl())
}
} else {
tryUseApi()
}
}
the code below should be called from activity with previously added intent filter to catch redirect intent from browser
launch {
grapi.loginEnd(intent) { ok ->
if (ok) {
// here we can start using api!
tryUseApi()
}
}
}
and that's it for login. You can start making a requests to API. The sdk will keep access token at private shared prefs so you can just start using the api second time the user gets into your app.
Requests
launch {
val userId = grapi.getUserId()
val shelves = grapi.getUserShelves(1, userId.id)
val reviews = grapi.getReviewList(
userId.id,
"read",
1, 2,
sort = Sort.NUM_PAGES,
order = Order.DESCENDING
)
val book = grapi.getBookByISBN("837054150X")
val book2 = grapi.getBookByGRID("13588846")
val res = grapi.getSearchResults("Wiedลบmin")
val user = grapi.getUser(userId.id)
val allReviews = grapi.getAllReviews(userId.id, shelf = "favorites")
// concurrent (~x2 faster) version of getAllReviews
val allReviews2 = grapi.getAllReviewsConcurrent(userId.id, shelf = "favorites")
val allShelves = grapi.getAllShelves(userId.id)
}
As you can see at sample app, Iโm launching coroutines from ScoupedActivity context. Beware not to use requests methods from main thread.
coffee โ๏ธ