Last active
August 10, 2016 22:26
-
-
Save juil/80abf80c1c82290af73eb72a1ab46389 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.juilyoon.booklook; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.net.ConnectivityManager; | |
import android.net.NetworkInfo; | |
import android.net.Uri; | |
import android.os.AsyncTask; | |
import android.support.v7.app.AppCompatActivity; | |
import android.os.Bundle; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.AdapterView; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import android.widget.ListView; | |
import android.widget.Toast; | |
import org.json.JSONArray; | |
import org.json.JSONException; | |
import org.json.JSONObject; | |
import java.io.ByteArrayOutputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.UnsupportedEncodingException; | |
import java.net.HttpURLConnection; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.util.ArrayList; | |
public class SearchActivity extends AppCompatActivity { | |
private final String DEBUG_TAG = "SearchActivity"; | |
private static final String API_URL = "https://www.googleapis.com/books/v1/volumes"; | |
// Full list of parsed Books | |
private ArrayList<Book> list = new ArrayList<Book>(); | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_search); | |
ListView bookList = (ListView) findViewById(R.id.searchResults_view); | |
bookList.setEmptyView(findViewById(R.id.emptyList_view)); | |
if (savedInstanceState != null && savedInstanceState.containsKey("key")) { | |
list = savedInstanceState.getParcelableArrayList("key"); | |
updateResults(list); | |
} | |
Button searchButton = (Button) findViewById(R.id.search_button); | |
searchButton.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
searchBooks(); | |
} | |
}); | |
} | |
@Override | |
protected void onSaveInstanceState(Bundle outState) { | |
outState.putParcelableArrayList("key", list); | |
super.onSaveInstanceState(outState); | |
} | |
private void searchBooks(){ | |
ConnectivityManager connectivityManager = (ConnectivityManager) | |
getSystemService(Context.CONNECTIVITY_SERVICE); | |
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); | |
if (networkInfo != null && networkInfo.isConnected()) { | |
// Search for query | |
EditText searchTextView = (EditText) findViewById(R.id.search_bar); | |
String query = searchTextView.getText().toString(); | |
new BookSearchAsyncTask().execute(query.split(" ")); | |
} | |
else { | |
Toast.makeText(this, "No network connection available.", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
private void updateResults(final ArrayList<Book> bookList) { | |
// Handle 0 case | |
if (bookList.isEmpty()) { | |
Toast.makeText(this, "No results found.", Toast.LENGTH_SHORT).show(); | |
} | |
else { | |
ListView searchResultsView = (ListView) findViewById(R.id.searchResults_view); | |
searchResultsView.setAdapter(new BookListAdapter(this, bookList)); | |
// Set each item linked to info page | |
searchResultsView.setOnItemClickListener(new AdapterView.OnItemClickListener() { | |
@Override | |
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { | |
Intent intent = new Intent(Intent.ACTION_VIEW); | |
intent.setData(Uri.parse(bookList.get(position).getInfoUrl())); | |
startActivity(intent); | |
} | |
}); | |
} | |
} | |
private ArrayList<Book> extractBooks(String jsonResponse) { | |
ArrayList<Book> books = new ArrayList<Book>(); | |
try { | |
JSONObject root = new JSONObject(jsonResponse); | |
JSONArray bookList = root.optJSONArray("items"); | |
// Variables that need to be extracted | |
String title; | |
ArrayList<String> authors = new ArrayList<>(); | |
String description; | |
String thumbnailUrl; | |
String infoUrl; | |
// Iterate through bookList and add Book objects to books ArrayList | |
for (int i=0; i < bookList.length(); i++) { | |
JSONObject book = bookList.optJSONObject(i); | |
JSONObject volumeInfo = book.optJSONObject("volumeInfo"); | |
title = volumeInfo.optString("title"); | |
JSONArray authorList = volumeInfo.optJSONArray("authors"); | |
for (int j=0; j < authorList.length(); j++) { | |
authors.add(authorList.optString(j)); | |
} | |
description = book.optJSONObject("searchInfo").optString("textSnippet"); | |
thumbnailUrl = volumeInfo.optJSONObject("imageLinks").optString("smallThumbnail"); | |
infoUrl = volumeInfo.optString("infoLink"); | |
// Add Book object to books | |
books.add(new Book(title, authors.toArray(new String[0]), description, thumbnailUrl, infoUrl)); | |
} | |
} catch (JSONException e) { | |
Log.e(DEBUG_TAG, "Problem parsing JSON results.", e); | |
} finally { | |
return books; | |
} | |
} | |
private class BookSearchAsyncTask extends AsyncTask<String, Void, String> { | |
@Override | |
protected String doInBackground(String... query) { | |
// Create URL object for search query | |
URL url = createUrl(query); | |
// Perform an HttpRequest to Google Books api and return JSON response | |
String jsonResponse = ""; | |
try { | |
jsonResponse = makeHttpRequest(url); | |
} | |
catch (IOException e) { | |
Log.e(DEBUG_TAG, "Problem making the HTTP request.", e); | |
} | |
// TODO: Set item thumbnail image from url | |
return jsonResponse; | |
} | |
/** | |
* Update the screen with search results | |
*/ | |
@Override | |
protected void onPostExecute(String books){ | |
if (books == null) { | |
return; | |
} | |
list = extractBooks(books); | |
updateResults(list); | |
} | |
/** | |
* Returns a new URL object from given String URL | |
*/ | |
private URL createUrl(String[] query) { | |
URL url = null; | |
try { | |
// Generate single string for all query words | |
if (query.length > 0) { | |
StringBuilder queryString = new StringBuilder(); | |
queryString.append(query[0]); | |
for (int i = 1; i < query.length; i++) { | |
// Add a space and next word of query | |
queryString.append("+" + query[i]); | |
} | |
url = new URL(API_URL + "?q=" + queryString.toString()); | |
} | |
} catch (MalformedURLException e) { | |
Log.e(DEBUG_TAG, "Error generating URL.", e); | |
return null; | |
} | |
return url; | |
} | |
// Given a URL, establishes an HttpUrlConnection and retrieves | |
// the web page content as a InputStream, which it returns as | |
// a string. | |
private String makeHttpRequest(URL url) throws IOException { | |
// Handle empty url | |
if (url == null) { return null; } | |
String jsonResponse = ""; | |
HttpURLConnection urlConnection = null; | |
InputStream inputStream = null; | |
try { | |
urlConnection = (HttpURLConnection) url.openConnection(); | |
urlConnection.setReadTimeout(10000 /* milliseconds */); | |
urlConnection.setConnectTimeout(15000 /* milliseconds */); | |
urlConnection.setRequestMethod("GET"); | |
urlConnection.connect(); | |
// Test response code | |
int responseCode = urlConnection.getResponseCode(); | |
if (responseCode == 200) { | |
inputStream = urlConnection.getInputStream(); | |
jsonResponse = readFromStream(inputStream); | |
} else { | |
Log.e(DEBUG_TAG, "Connection error " + responseCode); | |
} | |
} catch (IOException e) { | |
Log.e(DEBUG_TAG, "Trouble retrieving JSON results.", e); | |
} finally { | |
// Make sure urlConnection and inputStream are closed | |
if (urlConnection != null) { | |
urlConnection.disconnect(); | |
} | |
if (inputStream != null) { | |
inputStream.close(); | |
} | |
} | |
return jsonResponse; | |
} | |
/** | |
* Reads an InputStream and converts to a string | |
* | |
* @param stream | |
* @return String: converted input | |
* @throws IOException | |
* @throws UnsupportedEncodingException | |
*/ | |
public String readFromStream(InputStream stream) throws IOException, UnsupportedEncodingException { | |
ByteArrayOutputStream output = new ByteArrayOutputStream(); | |
byte[] buffer = new byte[1024]; | |
int length; | |
while ((length = stream.read(buffer)) != -1) { | |
output.write(buffer, 0, length); | |
} | |
return output.toString("UTF-8"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment