How to parse nested JSON on Android with help JsonReader? - java

This is my first time working with Android and I need to parse the JSON nested from the API. In the example below I managed to parse one JSON object, the value "title" is https://jsonplaceholder.typicode.com/posts/1. How do I change the code to look through all the JSON objects in the loop and extract "title" from them - https://jsonplaceholder.typicode.com/posts/?
P.S. If possible, I would not like to use the new Maven/Gradle dependencies.
package org.newwheel.app;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.JsonReader;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new RequestAsync().execute();
}
public class RequestAsync extends AsyncTask<String,String,List<String>> {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected List<String> doInBackground(String... strings) {
List<String> projectList = new ArrayList<>();
try {
// Create URL
URL newWheelEndpoint = new URL("https://jsonplaceholder.typicode.com/posts/1");
// Create connection
HttpsURLConnection myConnection = (HttpsURLConnection) newWheelEndpoint.openConnection();
if (myConnection.getResponseCode() == 200) {
InputStream responseBody = myConnection.getInputStream();
InputStreamReader responseBodyReader = new InputStreamReader(responseBody, StandardCharsets.UTF_8);
JsonReader jsonReader = new JsonReader(responseBodyReader);
jsonReader.beginObject(); // Start processing the JSON object
while (jsonReader.hasNext()) { // Loop through all keys
String key = jsonReader.nextName(); // Fetch the next key
if (key.equals("title")) { // Check if desired key
// Fetch the value as a String
String value = jsonReader.nextString();
// Do something with the value
// ...
projectList.add(value);
break; // Break out of the loop
} else {
jsonReader.skipValue(); // Skip values of other keys
}
}
jsonReader.close();
myConnection.disconnect();
} else {
// Error handling code goes here
}
} catch (IOException e) {
e.printStackTrace();
}
return projectList;
}
#Override
protected void onPostExecute(List<String> list) {
if(list!=null){
String[] array = list.toArray(new String[0]);
// Get element ListView
ListView countriesList = (ListView) findViewById(R.id.countriesList);
// Create adapter
ArrayAdapter<String> adapter = new ArrayAdapter(MainActivity.this,
android.R.layout.simple_list_item_1, array);
// Install for list adapter
countriesList.setAdapter(adapter);
}
}
}
}

Related

Java onItemSelectedListener and Spinner not returning Anything

I'm building a currency converter (get from API, dynamically fills lists to create available currencies, select two currencies and return the rate. It seems a right of passage exercise).
I've been trying to get a Spinner to work, but despite my best efforts I can't seem to get the listener to do anything when I select a value from the list. When I do click a value, the logs do return something (see below), but I don't know what it means, and why it's not returning the System.out.println("yay") call I want.
D/OpenGLRenderer: endAllActiveAnimators on 0xa7040980
(DropDownListView) with handle 0x95c21270".
The array adapter is properly filling the spinner list from an ArrayList<string> I get get from API and a JSON Object. The listener code looks correct based on the examples I found on S.O. so far.
I wonder if it's an ordering issue in my code? Or something else.
package com.timlee.currencymate;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import org.json.JSONException;
import org.json.JSONObject;
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.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
public class MainActivity extends AppCompatActivity {
// public variables
String uRLResultString = "";
ArrayList <String> currencies = new ArrayList<String>();
Spinner currencyOneSpinner;
Spinner currencyTwoSpinner;
// get data from api
public class DownloadTask extends AsyncTask <String, Void, String> {
#Override
protected String doInBackground(String... urls) {
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection)url.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char current = (char) data;
uRLResultString += current;
data = reader.read();
}
return uRLResultString;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//System.out.println(result);
//if get current list then run this, else run something else
getCurrencyList();
}
}
//gets the list of currecies
public void getCurrencyList () {
try {
JSONObject jsonObject = new JSONObject(uRLResultString);
String base = jsonObject.getString("base");
String rates = jsonObject.getString("rates");
currencies.add(base);
System.out.println(rates);
JSONObject jSonObj = new JSONObject(rates);
Iterator<String> keys = jSonObj.keys();
while (keys.hasNext()) {
String key = (String)keys.next();
currencies.add(key);
if (jSonObj.get(key) instanceof JSONObject) {
}
}
Collections.sort(currencies, String.CASE_INSENSITIVE_ORDER);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
currencies = new ArrayList<String>();
String currencyURL = "http://api.fixer.io/latest?base=AUD";
DownloadTask task = new DownloadTask();
task.execute(currencyURL);
// apply Array Adapter and listener
currencyOneSpinner = (Spinner)findViewById(R.id.spinnerCurrencyOne);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this,android.R.layout.simple_spinner_item,currencies);
currencyOneSpinner.setAdapter(arrayAdapter);
currencyOneSpinner.setOnItemSelectedListener (new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
System.out.println("yay");
return;
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
System.out.println("neyh");
return;
}
});
}
}
You did not set a dropdown view for the adapter. Add this line above setOnItemCLickListener
currencyOneSpinner.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
And Since you're using an AsyncTask don't forget to call the below line everytime you update the list.
arrayAdapter.notifyDataSetChanged();
NOTE: You have to initialize the adapter globally.

Listview not getting populated and is empty. Arrayadapter seems to be working fine

I am new to Android so I am sorry if this is a mundane question. I am working on one of the exercises in a tutorial and I have a simple list which is supposed to display the data I got from a website. My listview is empty despite my adapter being populated correctly. I tried printing the adapter objects and it is working fine. Please help. Thanks in advance.
MainAcitvity.java
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
public class MainActivity extends AppCompatActivity {
private static String USGS_URL = "https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2014-01-01&endtime=2014-12-01&minmagnitude=7";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DownloadTask task = new DownloadTask();
ArrayList<String> place = new ArrayList<>();
try {
place = task.execute(USGS_URL).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
ArrayAdapter<String> placesAdapter = new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_list_item_1,place);
ListView listView = (ListView)findViewById(R.id.listView);
listView.setAdapter(placesAdapter);
}
private class DownloadTask extends AsyncTask<String, Void, ArrayList<String>>
{
#Override
protected ArrayList<String> doInBackground(String... strings) {
ArrayList<String > place = QueryUtils.fetchData(strings[0]);
}return place;
}
}
}
QueryUtils.java
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import javax.net.ssl.HttpsURLConnection;
public final class QueryUtils {
private QueryUtils() {
}
protected static ArrayList<String> fetchData(String rawStream) {
URL newUrl = null;
try {
newUrl = createUrl(rawStream);
Log.i("QueryUtils.java", newUrl.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
}
ArrayList<String> values = QueryUtils.makeHttpRequest(newUrl);
}return values;
}
private static URL createUrl(String rawStream) throws MalformedURLException {
URL url = new URL(rawStream);
return url;
}
public static ArrayList<String> makeHttpRequest(URL newUrl) {
HttpsURLConnection url = null;
InputStream in = null;
ArrayList<String> values = new ArrayList<>();
try {
url = (HttpsURLConnection) newUrl.openConnection();
in = url.getInputStream();
String data = fetchJsonData(in);
values = fetchOutput(data);
} }catch (IOException e) {
e.printStackTrace();
}
finally {
if(url !=null)
url.disconnect();
}
return values;
}
private static ArrayList<String> fetchOutput(String data) {
String place = null;
ArrayList<String> values = new ArrayList<>();
try {
JSONObject baseJsonObject = new JSONObject(data);
JSONArray featuresAray =baseJsonObject.getJSONArray("features");
for(int i=0;i<featuresAray.length();i++) {
JSONObject firstArray = featuresAray.getJSONObject(i);
JSONObject properties = firstArray.getJSONObject("properties");
place = properties.getString("place");
values.add(place);
}
} catch (JSONException e) {
e.printStackTrace();
}
return values;
}
private static String fetchJsonData(InputStream in) throws IOException {
StringBuilder output = new StringBuilder();
InputStreamReader inReader = new InputStreamReader(in);
BufferedReader reader = new BufferedReader(inReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
return output.toString();
}
}
So the solution was really really stupid. I cant believe I wasted so much time over this. Apparently the text was white and that's why my listView seemed empty :(:(

android json parser load more data

Because my json source is sometimes too long, and my android app crashes if it takes too long to load, i want to modify my code, so that when the user scrolls down to automaticaly load data or if is more simple, i would ike to add a button "Load More". Here is my existing code. What is the part i must modify for adding autoload or maybe a "Load More" button? Thanks!
package com.radioxxx.aacplay;
import android.app.DownloadManager;
import android.app.Fragment;
import android.app.ListFragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class FazeNoi extends ListFragment {
JSONParser2 jsonParser = new JSONParser2();
private ProgressDialog pDialog;
ArrayList<HashMap<String, String>> tracksList;
JSONArray albums = null;
String nume_piesa, cale;
String titlu;
private static final String URL_ALBUMS = "http://www.radioxxx.ro/json-news";
private static final String TAG_TITLU = "Titlu";
private static final String TAG_POZA = "FazeNoiID";
private static final String TAG_NUME = "CMSdate";
private static final String TAG_CALE = "URL";
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
tracksList = new ArrayList<HashMap<String, String>>();
new LoadTracks().execute();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_fazenoi, container, false);
return rootView;
}
class LoadTracks extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Se incarca ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
//params.add(new BasicNameValuePair(TAG_ID, album_id));
String json = jsonParser.makeHttpRequest(URL_ALBUMS, "GET",
params);
Log.d("Track List JSON: ", json);
try {
JSONArray albums = new JSONArray(json);
for (int i = 0; i < albums.length(); i++) {
JSONObject c = albums.getJSONObject(i);
//String poza = c.getJSONArray("PozaPrincipalaMedia").getJSONObject(0).getString("thumb");
String track_no = String.valueOf(i + 1);
String poza = c.getJSONObject("PozaPrincipalaMedia").getString("thumb");
String idpoza = c.getJSONObject("PozaPrincipalaMedia").getString("id");
String nume = c.getString(TAG_TITLU);
String cale = c.getString(TAG_CALE);
HashMap<String, String> map = new HashMap<String, String>();
map.put("track_no", track_no + ".");
map.put(TAG_POZA, poza);
map.put(TAG_NUME, nume);
map.put(TAG_CALE, cale);
tracksList.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
getActivity().runOnUiThread(new Runnable() {
public void run() {
ListAdapter adapter = new SimpleAdapter(
getActivity(), tracksList,
R.layout.list_faze, new String[] {TAG_POZA, "track_no", TAG_NUME }, new int[] {
R.id.list_image,
R.id.track_no, R.id.nume_piesa });
setListAdapter(adapter);
//TextView text = (TextView) getActivity().findViewById(R.id.version);
//text.setText(titlu);
}
});
}
}
}
I'm going to post my comment as an answer, I believe it's the easiest way to quickly solve your problem. If you can control how much JSON is being sent on the server side, then make requests from your java app for page 1, page 2 etc.
Page 1,page 2,etc... could just send out small portions of the JSON you need, then attach a listener (button/scrollview) to request the next page, so on an so forth. Hope this helps!

setListAdapter unable to be resolved

a real amateur developer here in dire need of some assistance. I've been trying to parse JSON data and turn it into a list of items, but I am having difficulties attempting to use the setListAdapter method despite importing it into the class. Any help would be massively appreciated.
Here is my main activity, error is in the onPostExecute method
import java.io.IOException;
import java.util.List;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import android.app.Activity;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
public class JSON extends Activity {
// Coordinates used for centering the Map
private final static String UNAME = "aporter";
private final static String URL = "http://api.geonames.org/earthquakesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&username="
+ UNAME;
public static final String TAG = "MapsEarthquakeMapActivity";
// Set up UI and get earthquake data
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new HttpGetTask().execute(URL);
}
private class HttpGetTask extends
AsyncTask<String, Void, List<GeonameRec>> {
AndroidHttpClient mClient = AndroidHttpClient.newInstance("");
#Override
protected List<GeonameRec> doInBackground(String... params) {
HttpGet request = new HttpGet(params[0]);
JSONResponseHandler responseHandler = new JSONResponseHandler();
try {
// Get Earthquake data in JSON format
// Parse data into a list of EarthQuakeRecs
return mClient.execute(request, responseHandler);
} catch (ClientProtocolException e) {
Log.i(TAG, "ClientProtocolException");
} catch (IOException e) {
Log.i(TAG, "IOException");
}
return null;
}
#Override
protected void onPostExecute(List<GeonameRec> result) {
if (null != mClient)
mClient.close();
setListAdapter(new ArrayAdapter<String>(
JSON.this,
R.layout.listitem, result));
}
}
}
}
And here is my class where I format the JSON response.
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.impl.client.BasicResponseHandler;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
public class JSONResponseHandler implements
ResponseHandler<List<GeonameRec>> {
#Override
public List<GeonameRec> handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
List<GeonameRec> result = new ArrayList<GeonameRec>();
String JSONResponse = new BasicResponseHandler()
.handleResponse(response);
try {
JSONObject object = (JSONObject) new JSONTokener(JSONResponse)
.nextValue();
JSONArray earthquakes = object.getJSONArray("earthquakes");
for (int i = 0; i < earthquakes.length(); i++) {
JSONObject tmp = (JSONObject) earthquakes.get(i);
result.add(new GeonameRec(
tmp.getDouble("lat"),
tmp.getDouble("lng")));
}
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
setListAdapter method is available in ListActivity not in Activity.
to do so in an Activity sub class, you should define your ListView and call listView.setAdapter

errors in extracting json object

I have to retrieve json object from json file from this url.
My code is throwing java.lang.RuntimeException in doInBackground() and string to jsonObject conversion exception.
Can anyone help me at this? I am new to Android programming.
package course.examples.networkingearthquake;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.os.AsyncTask;
import android.widget.Button;
import android.view.View;
import android.widget.TextView;
import android.widget.EditText;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import android.net.http.AndroidHttpClient;
public class HttpActivity extends ActionBarActivity {
TextView mTextView;
EditText etInput;
TextView input;
String number;//edited
int num;//edited
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_socket);
mTextView = (TextView)findViewById(R.id.text1);
input = (TextView)findViewById(R.id.input);
etInput = (EditText)findViewById(R.id.etInput);
input.setText("Input");
//number = etInput.getText().toS();
final Button btDisplay = (Button)findViewById(R.id.btDisplay);
btDisplay.setText("DISPLAY");
btDisplay.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
new HttpGetTask().execute();
}
});
}
private class HttpGetTask extends AsyncTask<Void, Void, String>{
private static final String TAG = "HttpGetTask";
private static final String URL = "http://earthquake.usgs.gov/earthquakes/feed/geojsonp/2.5/week";
AndroidHttpClient mClient = AndroidHttpClient.newInstance("");
#Override
protected String doInBackground(Void... params){
HttpGet request = new HttpGet(URL);
JSONResponseHandler responseHandler = new JSONResponseHandler();
// ResponseHandler<String> responseHandler = new BasicResponseHandler();
try{
return mClient.execute(request,responseHandler);
}catch(ClientProtocolException exception){
exception.printStackTrace();
}catch(IOException exception){
exception.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result){
if(null != mClient)
mClient.close();
mTextView.setText(result);
}
}
private class JSONResponseHandler implements ResponseHandler<String>{
#Override
public String handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
String result = null;
String JSONResponse = new BasicResponseHandler().handleResponse(response);
JSONResponse = JSONResponse.substring(17, JSONResponse.length()-3);
num = Integer.parseInt(number);// edited
try {
JSONObject responseObject = (JSONObject) new JSONTokener(
JSONResponse).nextValue();
JSONArray features = responseObject.getJSONArray("features");
JSONObject retObject = (JSONObject)features.get(num);//edited
// JSONObject geometry = (JSONObject)retObject.get("geometry");
result = retObject.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
The JSON returned by the URL you specify containts eqfeed_callback() which needs to be stripped in order to make it valid JSON.
It seems like you have done this in your response handler, but you are cutting off one character too much at both the start and the end.
Try this:
JSONResponse = JSONResponse.substring(16, JSONResponse.length()-2);

Categories

Resources