I have shopping cart program and I want to get product names using json from php file.
I can get the the json successfully from PHP file but when I put it in this class its not working and when I run the app it show nothing as name in listview !
here is part of the code:
public static List<Product> getCatalog(Resources res){
System.out.println("*****JARRAY*****" + CatalogActivity.name1);
if(catalog == null) {
catalog = new Vector<Product>();
catalog.add(new Product(name1, res
.getDrawable(R.drawable.deadoralive),
"Dead or Alive by Tom Clancy with Grant Blackwood", 29.99));
catalog.add(new Product("Watchmen", res
.getDrawable(R.drawable.watchmen),
"Watchmen by Alan Moore and Dave Gibbons", 14.99));
}
return catalog;
}
public void ListDrwaer() {
List<Map<String, String>> productList = new ArrayList<Map<String, String>>();
try {
JSONObject jsonResponse = new JSONObject(jsonResult);
JSONArray jsonMainNode = jsonResponse.optJSONArray("products");
// System.out.println("*****JARRAY*****" + jsonMainNode.getJSONObject(0));
pro1 = jsonMainNode.getJSONObject(1);
pro2 = jsonMainNode.getJSONObject(2);
name1 = pro1.getString("name");
// System.out.println("*****JARRAY*****" + data);
System.out.println("*****JARRAY*****" + pro2);
} catch (JSONException e) {
Toast.makeText(getApplicationContext(), "Error" + e.toString(),
Toast.LENGTH_SHORT).show();
}
The code get the name1 string well but It don't show it in the listview...
I need to do something which it get the name1 from the web first, put it in getCatalog class and then make the listview and show the content...
how can I do that?
Related
I'm creating an android app and i have a relatively large amount of data (mostly in text form and as key->string pairs) that i want to display in my app.
The problem is i don't want to enter the data in my app's code,meaning feel each TextView manually with the associated data.i don't feel that to be right!
I want my app to read this data from a file(maybe a JSON?) and then associate each key-> string pair with the related TexView.
To be more clear, i need to read from a prepared text file and use that text inside my app, AND i want to do this offline,i dont want to use any webservic
How should i accomplish this? should i use a database or room?Then how should i feel the database manually without using insert codes inside the app?
Use Volley for JSON Parsing
private static final String url ="your url";
Create a method
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Please wait, while we load the data");
progressDialog.show();
*make a String or JSON request*
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
newurl, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("response", response.toString());
Log.i("updated Url",newurl);
progressDialog.dismiss();
*then move into the json and create JSON object or JSON Array to get their String values*
try {
JSONObject data = response.getJSONObject("data");
JSONArray onwardflights = data.getJSONArray("data_key");
for (int i = 0; i < onwardflights.length(); i++) {
JSONObject onwardFlightsChild = onwardflights.getJSONObject(i);
String arrival,deparutre,duration,flightno,grossamount,image,direct;
JSONObject object = onwardFlightsChild.getJSONObject("data_key");
Onwardflights onwardflights1 = new Onwardflights(
arrival = onwardFlightsChild.getString("data_key"),
deparutre = onwardFlightsChild.getString("data_key"),
duration = onwardFlightsChild.getString("data_key"),
flightno = onwardFlightsChild.getString("data_key"),
direct = onwardFlightsChild.getString("data_key"),
origin = onwardFlightsChild.getString("data_key"));
Log.i("Origin",origin);
Fare fare = new Fare(
grossamount = object.getString("data_key")
);
onwardflights1.setFare(fare);
suggestionmodel.add(onwardflights1);
}
*Create an instance of adapter and pass the parameters*
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(suggestionmodel,getApplicationContext());
recyclerView.setAdapter(recyclerAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("THIS", "Error: " + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(jsonObjReq);
}
You could simply use a JSON file. Now, the question is: How do you ship a JSON file with your app so that it's available at Runtime? You can use any of these methods:
Put it in the directory res/raw/ and read it using the Resources class (it has a openRawResource() method)
Put it in the assets/ directory and read it in using the AssetManager class (it has a open() method that returns an InputStream)
I hope this helps... Merry coding!
I am working on an app in Android Studio that downloads a json file from a php query, however when I have managed to read the contents of the json file from android, this contents does not behave as text, because when comparing a text entered from the app against the read from the json file, it never matches despite being the same text. (Example: password text from app and the password from the json file).
Php Code:
<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);
include('functions.php');
$col=$_GET["col"];
$colbus=$_GET["colbus"];
$tabla=$_GET["nomtable"];
$todfilas=$_GET["todasf"];
$dbuser =$_GET["username"];
$dbpass=$_GET["password"];
$dbbase=$_GET["dbname"];
//echo "$todfilas <br>";
if($todfilas == 1){
$sqlt="SELECT * FROM $tabla";
}else{
$sqlt="SELECT * FROM $tabla WHERE $col='$colbus'";
}
//echo "$sqlt <br>";
if($resultset=getSQLResultSet($sqlt,$dbuser,$dbpass,$dbbase)){
while ($row = $resultset->mysqli_fetch_array(MYSQLI_NUM)){
echo json_encode($row);
}
}
?>
Code from Android Studio:
private class ConsultData extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
// params comes from the execute() call: params[0] is the url.
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return "No es posible cargar pagina web o la direccion es invalida!";
}
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(String result) {
JSONArray ja = null;
try {
ja = new JSONArray(result);
Log.d("Password:",ja.getString(7)+"="+logPass.getText().toString().trim());
logPass2.setText(ja.getString(7).trim());
String pass1 =logPass2.toString();
String pass0 = logPass.toString().trim();
if(pass0==pass1){
showAlertDialog("Session:","login is valid!");
} else{
showAlertDialog("Session:","password does not match!");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
I'm not sure if the way to create the json file in the php query is the problem? because I can see the contents of the json array in Android Studio, but when I compare text from json array, they do not match even if they are the same ("123" = "123").
As seeing your code you doing so many mistakes like you are getting textview value thats not right way
change code like this
String pass1 =logPass2.getText().toString();
String pass0 = logPass.getText().toString().trim();
Also comparsion of string
if(pass0.equals(pass1)){
showAlertDialog("Session:","login is valid!");
} else{
showAlertDialog("Session:","password does not match!");
}
instead of this
if(pass0==pass1){
showAlertDialog("Session:","login is valid!");
} else{
showAlertDialog("Session:","password does not match!");
}
In Android web service using POST method of REST TEMPLATE, I am trying to send an object to server which contains few parameters and and 2 Objects. Those 2 Objects contains few parameters and 3 Lists of different Objects and each of those 3 Lists of Objects contains few parameters inside them and 1 List of Object that contains a byte array alone. Like in the below pics:
Pic 1[Main Object(The one I am trying to send)]:
Pic 2[Object inside the Main Object comprising 3 Lists of Objects]:
Pic 3[An Object as List comprising 1 List of Another Object inside it, likewise for the other 2(Accommodation & Others)]:
Pic 4[List of Object inside the sub-Object containing a byre array parameter alone]:
And my code for webservice POST method:
public static final String capUrl = "http://192.168.1.7:8084/CAPWS";
public Expenses setExpensesByBatch(Expenses expenses) {
try {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
list.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(list);
String b = restTemplate.postForObject(capUrl + "/UX/", expenses, String.class);
Log.e("String ===============b", b + " ++++");
} catch (Exception e) {
e.printStackTrace();
Log.e("expObjPost_WsCli_EX", e.toString());
}
return expenses;
}
Whatever I do it returns org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type
My LOGCAT below:
My server side code:
#RequestMapping(value = CapRestURIConstants.UPDATEEXPENSES, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
String updateExpenses(#RequestBody Expenses expenses) {
String response = "true";
System.out.println("incoming--------" + "UPDATEEXPENSES");
try {
if (expenses != null) {
//System.out.println("expenses--------" + expenses);
int catType = expenses.getCategoryType();
String categoryType = String.valueOf(catType);
String categoryId = expenses.getCategoryId();
String batchId = expenses.getBatchId();
System.out.println("categoryType--------" + categoryType);
System.out.println("categoryId--------" + categoryId);
System.out.println("batchId--------" + batchId);
Batch batch = getBatchById(batchId);
if (batch != null) {
expenseDataNew(batch, expenses);
expenseImagesNew(batch, expenses);
}
}
} catch (Exception e) {
e.printStackTrace();
response = "faslse";
}
return response;
}
public void expenseDataNew(Batch batch, Expenses expenses) {
Session session = null;
Transaction transaction = null;
Gson gson = new Gson();
try {
LinkedTreeMap masterMap = (LinkedTreeMap) gson.fromJson(batch.getMasterJson(), Object.class);
LinkedTreeMap expenseObject = (LinkedTreeMap) masterMap.get("2007");
masterMap.replace(expenseObject, expenses);
String masterJson = gson.toJson(masterMap);
batch.setMasterJson(masterJson);
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
session.saveOrUpdate(batch);
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
}
}
public void expenseImagesNew(Batch batch, Expenses expenses) {
Session session = null;
Transaction transaction = null;
Gson gson = new Gson();
try {
// DIVERTING TO IMAGE DB
session = ImageHibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
if (expenses != null) {
int catType = expenses.getCategoryType();
String categoryType = String.valueOf(catType);
System.out.println("categoryType--------" + categoryType);
String categoryId = expenses.getCategoryId();
System.out.println("categoryId--------" + categoryId);
String travelExpenseImgId = "f257f225-41da-11e7-be05-001d92ba9634";
String accommodationExpenseImgId = "204b4baf-41db-11e7-be05-001d92ba9634";
String otherExpenseImgId = "45d31872-41db-11e7-be05-001d92ba9634";
AssessorExpense assessorExpense = expenses.getAssessorExpense();
TCExpense tCExpense = expenses.getTcExpense();
Boolean isTravel, isAccomadation, isOthers;
List<Travel> travelList;
List<Accomadation> accommodationList;
List<Others> othersList;
ArrayList proof;
Expense expense;
ExpenseImage expenseImage;
// categoryType: 1 = Assessor
// categoryType: 4 = TC
if (categoryType.equals("1")) {
if (assessorExpense != null) {
isTravel = assessorExpense.isTravel();
if (isTravel) {
travelList = (ArrayList) assessorExpense.getTravel();
System.out.println("travelList.size()==" + travelList.size());
expense = getExpense(travelExpenseImgId);
System.out.println("expense==travel==1==:" + expense);
String expenseStr = String.valueOf(expense);
System.out.println("expenseStr==travel==1==:" + expenseStr);
for (Travel travel : travelList) {
List<ExpenseImageObject> expenseImageObjects = (ArrayList) travel.getExpenseImageObjects();
System.out.println("travel==expenseImageObjects.size()== :" + expenseImageObjects.size());
for (ExpenseImageObject image : expenseImageObjects) {
System.out.println("expense===travel==for==:" + expense);
expenseImage = new ExpenseImage();
expenseImage.setBatchId(batch.getBatchId());
expenseImage.setCategoryId(expenses.getCategoryId());
expenseImage.setExpimgId(expenseStr);
expenseImage.setImage(image.getImage());
expenseImage.setStatus(1); // dummy status 1 - Travel, 2 - Accommodation, 3 - Other
session.saveOrUpdate(expenseImage);
}
}
}
}
}
}
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
}
}
I am actually trying to send an object with lists of data as well list of photos in each list to the server.
Browsed through several websites and almost all topics related to the error on Stack Overflow, Been sitting on this issue for more than a week. Hope I would find some help.
Try using "HttpHeaders" to set the content-type header explicitly to what is expected by the endpoint.
Then you use the "HttpEntity" with both your header and your body classes.
Example :
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<String> httpEntity = new HttpEntity<>("my body", requestHeaders);
byte[] response = restTemplate.postForObject(
"URL", httpEntity, byte[].class);
Change the call to something like this
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Accept","application/json;charset=utf-8");
RestTemplate restTemplate = new RestTemplate();
...
HttpEntity request = new HttpEntity(req, headers);
responseEntity = restTemplate.exchange(url, HttpMethod.POST, request,
String.class);
to specify content type
UPDATE
req is in fact body you send to the server. It could be e.g.
MultiValueMap<String, Object> req ...
There you in fact send request body and headers.
After a hell lot of research and experts suggestions, I finally managed to find the solution to my problem. The problem is not with the code. Its actually perfect. The problem is with the Objects I use to get & set. I am using NetBeans for server side coding. What I did was, I created my necessary Objects in Android studio, copied the parameters, getters & setters and pasted them on NetBeans, Object class. The problem was with the booleans I've been using. The booleans that are created on Android Studio didn't support on NetBeans in some cases, that prevented hitting the server. And after getting expert advice, I did the Object creation on NetBeans copied the parameters, getters & setters and pasted them on Android Studio Object class. And then it worked well. Took me more than 2 weeks to solve this issue. Hope this would be of some help.
I'm having trouble with my app that is supposed to take in user text input and search Google Books API. Thus far I am able to successfully take in user input, add it to the query string and start an AsyncTask, start HttpRequest, take the inputStream and build a string from it, create an array of items from the string, and then use a custom adapter to display that book listing on the screen for the user.
The trouble I'm having is that when the code runs (regardless of what the user inputs, be it food, greek, android, whatever) I only get one response showing up on the screen. I can't figure out why it's only showing up one book. The API query string specifies 10 (I've also used 2, 4, & 7) as the max result but I've thus far only gotten 1 list. After checking with the debugger I've narrowed it down to either the Stringbuilder stops after a certain length of input or my arraylist isn't creating other indices for the rest of the JSONObjects.
Below is the Book Activity code:
package com.ovidioreyna.android.googlebooksapiapp;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ListView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import static com.ovidioreyna.android.googlebooksapiapp.MainActivity.LOG_TAG;
public class BooksActivity extends AppCompatActivity {
//Creates blank global string which will be used the search parameters in this class
public String gglBookSearch = "https://www.googleapis.com/books/v1/volumes?q=";
//After the user enters what they want to search for we pass that in from the main activity
//and add it to our global variable here. We then add some modifiers so that we can control
//the amount of info being return. This will later be changed to 10 once the app is functioning
Context context = this;
String jsonResponse = "";
ListView booksListView;
BookAdapter adapter;
//inflates the book_layout.xml so we can see the book info
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.book_list);
//passes the user input to this activity
Bundle extras = getIntent().getExtras();
if (extras != null) {
String textSearchUpdate = extras.getString("EDITTEXTUPDATE");
//takes user input and appends it to the initial Google Books API Query
updateApiSearch(textSearchUpdate);
}
//creates an instance of BooksAsynTask and executes it
BooksAsyncTask task = new BooksAsyncTask();
task.execute();
}
//Sets the appropriate info to the appropriate textviews
private void updateUi(ArrayList<Books> books) {
//creates an instance of the book list
booksListView = (ListView) findViewById(R.id.book_list);
//creates an instance of the book adapter
adapter = new BookAdapter(context, new ArrayList<Books>());
//sets the adapter to the listview.xml
booksListView.setAdapter(adapter);
//in case user initiates multiple searches then we need to clear the adapter to start with
//clean adapter for the new search
adapter.clear();
adapter.addAll(books);
adapter.notifyDataSetChanged();
}
private class BooksAsyncTask extends AsyncTask<URL, Void, ArrayList<Books>> {
#Override
protected ArrayList<Books> doInBackground(URL... urls) {
//creates a new url object from the #gglBookSearch query
URL url = createUrl(gglBookSearch);
try {
//creates a string that will hold the raw data for the jsonarray
jsonResponse = makeHttpRequest(url);
Log.i(LOG_TAG, "JSON Results: " + jsonResponse);
} catch (IOException e) {
Log.e(LOG_TAG, "Error with make request", e);
}
//takes the raw string data and extracts it into an array
return extractBooks(jsonResponse);
}
#Override
protected void onPostExecute(ArrayList<Books> books) {
//checks to make sure that the arraylist books is not empty
if (books == null) {
return;
}
//if all goes well and books is populated then it displays that info
updateUi(books);
}
private URL createUrl(String stringUrl) {
//creates a new url object from the string passed in
URL url = null;
try {
url = new URL(stringUrl);
} catch (MalformedURLException exception) {
Log.e(LOG_TAG, "Error with creating URL", exception);
}
return url;
}
public ArrayList<Books> extractBooks(String jsonResponse) {
//craetes a new Arraylist that will hold all the json data
ArrayList<Books> books = new ArrayList<>();
//checks to see that the string passed in is not empty
if (TextUtils.isEmpty(jsonResponse)) {
return null;
}
try {
//creates a jsonObject to hold the data. Then delves into the Array items
JSONObject baseJsonResponse = new JSONObject(jsonResponse);
JSONArray itemsArray = baseJsonResponse.getJSONArray("items");
Log.i(LOG_TAG, "Length of books array: " + itemsArray.length());
//create empty local variables in case the JSON objects are null
String bookTitle = "";
String bookSubtitle = "";
String author = "";
String publishedDate = "";
for (int i = 0; i < itemsArray.length(); i++) {
//checks to see that the Array isn't empty
if (itemsArray.length() > 0) {
JSONObject firstItem = itemsArray.getJSONObject(i);
JSONObject volumeInfo = firstItem.getJSONObject("volumeInfo");
//checks to see if object is null, if not then executes code
if (!volumeInfo.isNull("title")) {
bookTitle = volumeInfo.getString("title");
}
//checks to see if object is null, if not then executes code
if (!volumeInfo.isNull("subtitle")) {
bookSubtitle = volumeInfo.getString("subtitle");
}
//creates an jsonArray object from the authors array
JSONArray authorArray = volumeInfo.getJSONArray("authors");
if (!authorArray.isNull(i)) {
if (authorArray.length() == 1) {
author = authorArray.getString(i);
} else {
for (int k = 0; k < authorArray.length(); k++) {
//checks to see if object is null, if not then executes code
if (!authorArray.isNull(k)) {
author = authorArray.getString(k) + ",";
}
}
}
}
//checks to see if object is null, if not then executes code
if (!volumeInfo.isNull("publishedDate"))
publishedDate = volumeInfo.getString("publishedDate");
//create a new instance of the Books class
Books book = new Books(bookTitle, bookSubtitle, author, publishedDate);
books.add(book);
}
return books;
}
} catch (JSONException e) {
Log.e(LOG_TAG, "Problem with parsing the books JSON results", e);
}
//if there is an error in the code above it returns null
return null;
}
private String makeHttpRequest(URL url) throws IOException {
//checks to see that the url object passed in is not empty. If empty then returns an
//empty string
if (url == null) {
return jsonResponse = "";
}
//creates two empty objects
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
//this is where we try to establish a connection and if successful take the input info
//and convert it into a usable form
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.connect();
if (urlConnection.getResponseCode() == 200) {
//if we get a success code from the server we proceed to convert the bits and
//bytes into a usuable form and ultimately convert it into a usable string.
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
//if we don't get a success code from the server we log it.
Log.e(LOG_TAG, "Error Response Code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem With Connection: ", e);
} finally {
//regardless if we are successful gettting an inputstream or not we disconnect and
//close the inputstream
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
inputStream.close();
}
}
//returns the string #jsonResponse whether it's empty or has information
return jsonResponse;
}
//uses StringBuilder to take the raw bits and make a legible string from it
private String readFromStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
//once the entire input stream has been built we output it to a string
return output.toString();
}
}
//takes the input text from the user and concatonates it to the query as well as adding a limit
//of 10 books at a time
public void updateApiSearch(String updatedEditText) {
gglBookSearch += updatedEditText;
gglBookSearch += "&maxResults=10";
}
}
Here is the link to the entire repo if anyone would like to have the entire code to mess with:
https://github.com/ovidioreyna/GoogleBooksAPIApp
Thanks in advance for your help
UPDATE:
So I created a log event to show the JSON results after jsonResponse = makeHttpRequest(url); and the logs showed this:
10-09 20:50:36.846 32119-32463/com.ovidioreyna.android.googlebooksapiapp I/MainActivity: JSON Results: { "kind": "books#volumes", "totalItems": 1431, "items": [ { "kind": "books#volume", "id": "vdXmDAAAQBAJ", "etag": "pSHAL8HBKSs", "selfLink": "https://www.googleapis.com/books/v1/volumes/vdXmDAAAQBAJ", "volumeInfo": { "title": "Molly on the Range", "subtitle": "Recipes and Stories from an Unlikely Life on a Farm", "authors": [ "Molly Yeh" ], "publisher": "Rodale", "publishedDate": "2016-10-04", "description": "In 2013, food blogger and classical musician Molly Yeh left Brooklyn to live on a farm on the North Dakota-Minnesota border, where her fiancé was a fifth-generation Norwegian-American sugar beet farmer. Like her award-winning blog My Name is Yeh, Molly on the Range chronicles her life through photos, more than 120 new recipes, and hilarious stories from life in the city and on the farm. Molly’s story begins in the suburbs of Chicago in the 90s, when things like Lunchables and Dunkaroos were the objects of her affection; continues into her New York years, when Sunday mornings meant hangovers and bagels; and ends in her beloved new home, where she’s currently trying to master the art of the hotdish. Celebrating Molly's Jewish/Chinese background with recipes for Asian Scotch Eggs and Scallion Pancake Challah Bread and her new hometown Scandinavian recipes for Cardamom Vanilla Cake and Marzipan Mandel Bread, Molly on the Range will delight everyone, from longtime readers to those discovering her glorious writing and recipes for the first time.", "industryIdentifiers": [ { "type": "ISBN_13", "identifier": "9781623366957" }, { "type": "ISBN_10", "identifier": "162336695X" } ], "readingModes": { "text": false, "image": false }, "pageCount": 304, "printType": "BOOK", "categories": [ "Cooking" ], "maturityRating": "NOT_MATURE", "allowAnonLogging": false, "contentVersion": "1.1.1.0.preview.0", "imageLinks": { "smallThumbnail": "http://books.google.com/books/content?id=vdXmDAAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api", "thumbnail": "http://books.google.com/books/content?id=vdXmDAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api" }, "language": "en", "previewLink": "http://books.google.com/books?id=vdXmDAAAQBAJ&printsec=frontcover&dq=Food&hl=&cd=1&source=gbs_api", "infoLink": "http://books.google.com/books?id=vdXmDAAAQBAJ&dq=Food&hl=&source=gbs_api", "canonicalVolumeLink": "http://books.google.com/books/about/Molly_on_the_Range.html?hl=&id=vdXmDAAAQBAJ" }, "saleInfo": { "country": "US", "saleability": "NOT_FOR_SALE", "isEbook": false }, "accessInfo": { "country": "US", "viewability": "PARTIAL", "embeddable": true, "publicDomain": false, "textToSpeechPermission": "ALLOWED", "epub": { "isAvailable": false }, "pdf": { "isAvailable": false }, "webReaderLink": "http://books.google.com/books/reader?id=vdXmDAAAQBAJ&hl=&printsec=frontcover&output=reader&source=gbs_api", "accessViewStatus": "SAMPLE", "quoteSharingAllowed": false }, "searchInfo": { "textSnippet": "Celebrating Molly's Jewish/Chinese background with recipes for Asian Scotch Eggs and Scallion Pancake Challah Bread and her new hometown Scandinavian recipes for Cardamom Vanilla Cake and Marzipan Mandel Bread, Molly on the Range will ..." } }, { "kind": "books#volume", "id": "DY-dBAAAQBAJ", "etag": "t4JLTMFKOGc", "selfLink": "https://www.googleapis.com/books/v1/volumes/DY-dBAAAQBAJ", "volumeInfo": { "title": "Real Baby Food", "subtitle": "Easy, All-Natural Recipes for Your Baby and Toddler", "authors": [ "Jenna Helwig" ], "publisher": "Houghton Mifflin Harcourt", "publishedDate": "2015-04-28", "description": "Simple Recipes for a Wholesome Start Nothing compares with making your own baby food: It's fresh and unprocessed, you choose what goes into it, and it is a delicious way to introduce your child to a world of flavors. In Real Baby Foo
10-09 20:50:36.861 32119-32463/com.ovidioreyna.android.googlebooksapiapp I/MainActivity: Length of books array: 10
I've also added a log event to show how long the array is and it shows up as 10. Which is strange since only two instances were written from the HttpRequest method.
You've returned the books too early in a for-loop. Check it carefully in BooksActivity line 144-186.
for (int i = 0; i < itemsArray.length(); i++) {
//checks to see that the Array isn't empty
if (itemsArray.length() > 0) {
JSONObject firstItem = itemsArray.getJSONObject(i);
JSONObject volumeInfo = firstItem.getJSONObject("volumeInfo");
//checks to see if object is null, if not then executes code
if (!volumeInfo.isNull("title")) {
bookTitle = volumeInfo.getString("title");
}
//checks to see if object is null, if not then executes code
if (!volumeInfo.isNull("subtitle")) {
bookSubtitle = volumeInfo.getString("subtitle");
}
//creates an jsonArray object from the authors array
JSONArray authorArray = volumeInfo.getJSONArray("authors");
if (!authorArray.isNull(i)) {
if (authorArray.length() == 1) {
author = authorArray.getString(i);
} else {
for (int k = 0; k < authorArray.length(); k++) {
//checks to see if object is null, if not then executes code
if (!authorArray.isNull(k)) {
author = authorArray.getString(k) + ",";
}
}
}
}
//checks to see if object is null, if not then executes code
if (!volumeInfo.isNull("publishedDate"))
publishedDate = volumeInfo.getString("publishedDate");
//create a new instance of the Books class
Books book = new Books(bookTitle, bookSubtitle, author, publishedDate);
books.add(book);
}
//See that? You return your books with only one extracted from your itemArray!!!!
return books;
}
After making a call to the "me/home" Graph API, while parsing the JSON result, I am trying to make another query using FQL. The FQL query problem was solved in my earlier question.
The background of my implementation is: I am using a BaseAdapter and from the main activity, I am sending the data parsed from JSON using multiple ArrayLists. If I am not making the FQL query, everything is peachy. But when I introduce the FQL query, the query is always run after the adapter has been set to the ListView. This keeps causing the arrayindexoutofbound exception.
This is the code that I am using including the additional FQL query while parsing the JSON result. To keep the code short, I will include the relevant part as the rest works just fine. If more is needed, however, I will put that up too.
// GET THE POST'S LIKES COUNT
if (json_data.has("likes")) {
JSONObject feedLikes = json_data.optJSONObject("likes");
String countLikes = feedLikes.getString("count");
postLikesCountArrayList.add(countLikes);
// TEST STARTS
Runnable run = new Runnable() {
#Override
public void run() {
graph_or_fql = "fql";
String query = "SELECT likes.user_likes FROM stream WHERE post_id = \'"
+ finalThreadID + "\'";
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
Utility.mAsyncRunner.request(null, params, new LikesListener());
}
};
TestNewsFeeds.this.runOnUiThread(run);
// TEST ENDS
} else {
String countLikes = "0";
postLikesCountArrayList.add(countLikes);
}
And this is the code for the LikesListener class. It is a private class declared in the same activity:
private class LikesListener extends BaseRequestListener {
#Override
public void onComplete(final String response, final Object state) {
// Log.e("response", response);
try {
JSONArray JALikes = new JSONArray(response);
// Log.v("JALikes", JALikes.toString());
for (int j = 0; j < JALikes.length(); j++) {
JSONObject JOTemp = JALikes.getJSONObject(j);
// Log.e("JOTemp", JOTemp.toString());
if (JOTemp.has("likes")) {
JSONObject optJson = JOTemp.optJSONObject("likes");
// Log.v("optJson", optJson.toString());
if (optJson.has("user_likes")) {
String getUserLikeStatus = optJson.getString("user_likes");
Log.e("getUserLikeStatus", getUserLikeStatus);
arrayLikeStatus.add(getUserLikeStatus);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
I have figured out using debugging that the cause of the crash is the setAdapter being called before the second query completes. I see the log's being added to logcat after the crash has occured.
Any help on a solution for this is appreciated
UPDATE: Figured out the solution almost when I was about to give up.
SOLUTION
So instead of calling the BaseRequestListener as used in the question, this modification had to be made.
try {
graph_or_fql = "fql";
String query = "SELECT likes.user_likes FROM stream WHERE post_id = \'"
+ finalThreadID + "\'";
// Log.d("finalThreadID", finalThreadID);
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
// Utility.mAsyncRunner.request(null, params, new LikesListener());
String fqlResponse = Utility.mFacebook.request(params);
// Log.e("fqlResponse", fqlResponse);
JSONArray JALikes = new JSONArray(fqlResponse);
// Log.v("JALikes", JALikes.toString());
for (int j = 0; j < JALikes.length(); j++) {
JSONObject JOTemp = JALikes.getJSONObject(j);
// Log.e("JOTemp", JOTemp.toString());
if (JOTemp.has("likes")) {
JSONObject optJson = JOTemp.optJSONObject("likes");
// Log.v("optJson", optJson.toString());
if (optJson.has("user_likes")) {
String getUserLikeStatus = optJson.getString("user_likes");
// Log.e("getUserLikeStatus", getUserLikeStatus);
arrayLikeStatus.add(getUserLikeStatus);
// Log.d("arrayLikeStatus", arrayLikeStatus.toString());
}
}
}
} catch (Exception e) {
// TODO: handle exception
}
Hope this helps someone save time if they are stuck like I was.