This app is supposed to parse some JSON data (hard coded for now) from the Google Books API, and pass an ArrayList of Books to the adapter that will display it on a ListView. The problem I have is that the JSON parse is returning null instead of the parsed data.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ProgressBar pBar;
List<MyTask> tasks;
ArrayList<Book> bookList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pBar = (ProgressBar) findViewById(R.id.progressBar);
pBar.setVisibility(View.INVISIBLE);
Button sButton = (Button) findViewById(R.id.s_button);
sButton.setOnClickListener(this);
tasks = new ArrayList<>();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.s_button: {
if (isOnline()) {
new MyTask().execute("https://www.googleapis.com/books/v1/volumes?q=millionare"); //https://www.googleapis.com/books/v1/volumes?q=soft+skills
} else {
Toast.makeText(this, "Connection failed", Toast.LENGTH_LONG).show();
}
break;
}
}
}
protected boolean isOnline() {
ConnectivityManager connectManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = connectManager.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
} else {
return false;
}
}
private class MyTask extends AsyncTask<String, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... urls) {
// params comes from the execute() call: params[0] is the url.
try {
return HttpManager.getData(urls[0]);
} catch (IOException e) {
return "Unable to retrieve web page. URL may be invalid.";
}
}
@Override
protected void onPostExecute(String result) {
bookList = BookJSONParser.parseFeed(result);
updateDisplay();
}
}
protected void updateDisplay() {
BookAdapter adapter = new BookAdapter(this, bookList);
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
}
}
public class BookJSONParser {
public static ArrayList<Book> parseFeed(String content) {
try {
JSONArray jsonArray = new JSONArray(content);
ArrayList<Book> bookList = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String name = object.getString("title").toString();
Book book = new Book(name);
bookList.add(book);
}
return bookList;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
}
public class BookAdapter extends ArrayAdapter<Book> {
public BookAdapter(Context context, ArrayList<Book> bookList) {
super(context, 0, bookList);
}
@Override
public View getView(int position, View convertedView, ViewGroup parent) {
View listItemView = convertedView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.list_item, parent, false);
}
Book currentBook = getItem(position);
TextView locationName = (TextView) listItemView.findViewById(R.id.book_title);
locationName.setText(currentBook.getTittle());
TextView locationAddress = (TextView) listItemView.findViewById(R.id.book_author);
locationAddress.setText(currentBook.getAuthor());
return listItemView;
}
}
public class HttpManager {
public static String getData(String myUrl) throws IOException {
// BufferedReader reader = null;
InputStream inputStream = null;
int len = 10000;
try {
URL url = new URL(myUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(10000 /* milliseconds */);
connection.setConnectTimeout(15000 /* milliseconds */);
connection.setRequestMethod("GET");
connection.setDoInput(true);
// Starts the query
connection.connect();
int response = connection.getResponseCode();
inputStream = connection.getInputStream();
// Convert the InputStream into a string
String contentAsString = readIt(inputStream, len);
return contentAsString;
// Makes sure that the InputStream inputStream closed after the app inputStream
// finished using it.
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
}
// Reads an InputStream and converts it to a String.
public static String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
Reader reader = null;
reader = new InputStreamReader(stream, "UTF-8");
char[] buffer = new char[len];
reader.read(buffer);
return new String(buffer);
}
}
public class Book {
private String mTittle;
/**
* This is the constructor.
* @param title is the book title being passed in.
*/
public Book(String title) {
mTittle = title;
}
public String getTittle() {
return mTittle;
}
public void setTittle(String tittle) {
mTittle = tittle;
}
}
FATAL EXCEPTION: main
Process: com.narvin.android.booklisting, PID: 3278
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)
at android.widget.ListView.setAdapter(ListView.java:502)
at com.narvin.android.booklisting.MainActivity.updateDisplay(MainActivity.java:113)
at com.narvin.android.booklisting.MainActivity$MyTask.onPostExecute(MainActivity.java:100)
at com.narvin.android.booklisting.MainActivity$MyTask.onPostExecute(MainActivity.java:79)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
The issue is that one of the arguments in
BookAdapter adapter = new BookAdapter(this, bookList);
isnull
for some reason. Try passingbookList
as an argument toupdateDisplay
and checking whether it's notnull
.It would appear you are getting a JSONParseException... therefore causing a NullPointerExpcetion for the List into the Adapter
That is your error, here is how you get it
And you use that null value here
Followed by
So, the way to fix that NullPointerExpception is to always return an ArrayList
to get json string from url you should do it like that
what you get from the url you provided is NOT jsonArray it's a jsonobject so I think this code will work "assuming that you did everything else correctly"
the you can do the for loop