Using Google Books Api In Android
Solution 1:
I just finished doing this myself. This is how I implemented it using an HttpURLConnection
and an AsyncTask
(I just call "https://www.googleapis.com/books/v1/volumes?q=isbn:"+yourISBN and parse the JSON):
// Received ISBN from Barcode Scanner. Send to GoogleBooks to obtain book information.classGoogleApiRequestextendsAsyncTask<String, Object, JSONObject>{
@OverrideprotectedvoidonPreExecute() {
// Check network connection.if(isNetworkConnected() == false){
// Cancel request.Log.i(getClass().getName(), "Not connected to the internet");
cancel(true);
return;
}
}
@OverrideprotectedJSONObjectdoInBackground(String... isbns) {
// Stop if cancelledif(isCancelled()){
returnnull;
}
String apiUrlString = "https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbns[0];
try{
HttpURLConnection connection = null;
// Build Connection.try{
URL url = newURL(apiUrlString);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(5000); // 5 seconds
connection.setConnectTimeout(5000); // 5 seconds
} catch (MalformedURLException e) {
// Impossible: The only two URLs used in the app are taken from string resources.
e.printStackTrace();
} catch (ProtocolException e) {
// Impossible: "GET" is a perfectly valid request method.
e.printStackTrace();
}
int responseCode = connection.getResponseCode();
if(responseCode != 200){
Log.w(getClass().getName(), "GoogleBooksAPI request failed. Response Code: " + responseCode);
connection.disconnect();
returnnull;
}
// Read data from response.StringBuilder builder = newStringBuilder();
BufferedReader responseReader = newBufferedReader(newInputStreamReader(connection.getInputStream()));
String line = responseReader.readLine();
while (line != null){
builder.append(line);
line = responseReader.readLine();
}
String responseString = builder.toString();
Log.d(getClass().getName(), "Response String: " + responseString);
JSONObject responseJson = newJSONObject(responseString);
// Close connection and return response code.
connection.disconnect();
return responseJson;
} catch (SocketTimeoutException e) {
Log.w(getClass().getName(), "Connection timed out. Returning null");
returnnull;
} catch(IOException e){
Log.d(getClass().getName(), "IOException when connecting to Google Books API.");
e.printStackTrace();
returnnull;
} catch (JSONException e) {
Log.d(getClass().getName(), "JSONException when connecting to Google Books API.");
e.printStackTrace();
returnnull;
}
}
@OverrideprotectedvoidonPostExecute(JSONObject responseJson) {
if(isCancelled()){
// Request was cancelled due to no network connection.showNetworkDialog();
} elseif(responseJson == null){
showSimpleDialog(getResources().getString(R.string.dialog_null_response));
}
else{
// All went well. Do something with your new JSONObject.
}
}
}
protectedbooleanisNetworkConnected(){
// Instantiate mConnectivityManager if necessaryif(mConnectivityManager == null){
mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
}
// Is device connected to the Internet?NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isConnected()){
returntrue;
} else {
returnfalse;
}
}
I've omitted the code for my dialog methods as they are not relevant. Hope this helps.
Solution 2:
To access Google Books API or any other REST APIs directly at HTTP level, you can use Volley if you are willing to write asynchronous code, or OkHttp for simpler synchronous requests. And there's also Android Asynchronous Http Client.
But what's even better, you can use Feign or Retrofit that abstract away the HTTP-level implementation details and provide fluent typesafe APIs on top of auto-generated implementation. Retrofit is the most used network library in Android, but Feign is used more in the wider Java ecosystem.
Here's an example using Feign for Google Books API, Retrofit is very similar.
API interface, implementation is auto-generated by Feign:
publicinterfaceGoogleBooksApi {
@RequestLine("GET /books/v1/volumes")
Results findBookByISBN(@QueryMap Map<String, Object> queryParameters);
}
API client code:
publicclassBookLookupService {
public Book fetchBookByISBN(String isbn)throws BookLookupException {
finalGoogleBooksApigoogleBooksApi= connect();
final Map<String, Object> queryParameters = newHashMap<>();
queryParameters.put("q", "isbn:" + isbn);
finalResultsapiResponse= googleBooksApi.findBookByISBN(queryParameters);
if (apiResponse == null || apiResponse.getTotalItems() < 1) {
thrownewBookLookupException("No books found for ISBN " + isbn);
}
final List<Result> results = apiResponse.getItems();
if (results == null || results.size() < 1) {
thrownewBookLookupException("Invalid items list for ISBN " + isbn);
}
finalBookbook= results.get(0).getBook();
return book;
}
privatestatic GoogleBooksApi connect() {
return Feign.builder()
.decoder(newGsonDecoder())
.logger(newLogger.ErrorLogger())
.logLevel(Logger.Level.BASIC)
.target(GoogleBooksApi.class, "https://www.googleapis.com");
}
}
Entities that model the API response structure:
publicclassResults {
int totalItems;
List<Result> items;
public int getTotalItems() {
return totalItems;
}
publicList<Result> getItems() {
return items;
}
}
publicclassResult {
// the JSON field is named volumeInfoBook volumeInfo;
publicBookgetBook() {
return volumeInfo;
}
}
publicclassBook {
privateString title;
privateList<String> authors;
publicStringgetTitle() {
return title;
}
publicList<String> getAuthors() {
return authors;
}
}
And last not least, test:
@RunWith(AndroidJUnit4.class)publicclassBookLookupServiceAndroidTest {
privateBookLookupServicebookLookupService=newBookLookupService();
@TestpublicvoidwhenMultipleLookupResultsThenReturnsFirst()throws Exception {
assertThat(bookLookupService.fetchBookByISBN("9780321356680").getTitle(),
is(equalTo("Effective Java, 2nd Edition")));
}
}
Note that you need to wrap the code in AsyncTask
to make it asynchronous as network requests are not allowed on main thread. The AsyncTask
should update the UI in onPostExecute()
.
Here's an example:
publicclassMainActivityextendsAppCompatActivity {
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
final Button fetchBookButton = (Button) findViewById(R.id.FetchBookButton);
fetchBookButton.setOnClickListener(newView.OnClickListener() {
@OverridepublicvoidonClick(View v) { newFetchBookTask().execute(getISBN()); }
});
}
privateStringgetISBN() {
final EditText isbnField = (EditText) findViewById(R.id.BookIsbnField);
return isbnField.getText().toString();
}
privatevoidshowMessage(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
classFetchBookTaskextendsAsyncTask<String, Void, Book> {
@OverrideprotectedBookdoInBackground(String... params) {
final String isbn = params[0];
try {
returnnewBookLookupService().fetchBookByISBN(isbn);
} catch (Exception e) {
Log.e("fetchBookByISBN", e.toString());
returnnull;
}
}
@OverrideprotectedvoidonPostExecute(Book book) {
if (book != null) {
showMessage("Got book: " + book.getTitle());
} else {
showMessage("Failed to fetch book");
}
}
}
}
Post a Comment for "Using Google Books Api In Android"