I am trying to get some data from a webservice, in my android app.
The code I am using is this:
#Override
protected String doInBackground(String... params) {
String highScore = null;
int points = 0;
try {
URI uri = new URI("http://vestsoft.somee.com/api/scores");
URL website = new URL(uri.toASCIIString());
InputStream inputStream = website.openStream();
InputSource input = new InputSource(inputStream);
SAXParserFactory saxp = SAXParserFactory.newInstance();
SAXParser sp = saxp.newSAXParser();
XMLReader xmlReader = sp.getXMLReader();
HighScoreHandler handler = new HighScoreHandler();
xmlReader.setContentHandler(handler);
xmlReader.parse(input); // Here is an exception thrown
highScore = handler.highScore.getUserName();
points = handler.highScore.getPoints();
} catch (Exception e) {
e.printStackTrace();
}
return highScore + " " + points;
}
I get an exception saying:
"At line 1, column 0: syntax error"
I don't know what I am doing wrong.
As you can see, the API I get my data from is:
http://vestsoft.somee.com/api/scores
Your XML lacks the correct header:
<?xml version="1.0" encoding="UTF-8"?>
Put that string at the top of your XML file and SAX Parser will stop bothering.
There are some really nice open source XML parsing tools out there to make this a lot easier. For example, to solve this with Simple XML, I would do it like this:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.squareup.okhttp.OkHttpClient;
public class MainActivity extends Activity {
public static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
URL website = new URL("http://vestsoft.somee.com/api/scores");
OkHttpClient client = new OkHttpClient();
HttpURLConnection conn = client.open(website);
conn.addRequestProperty("Accept", "application/xml");
InputStream stream = conn.getInputStream();
Serializer serializer = new Persister();
ArrayOfScore scoreArray = serializer.read(ArrayOfScore.class, stream);
// do something with the ArrayScore object here
} catch (Exception err) {
Log.i(TAG, err.toString());
}
}
};
new Thread(r).start();
}
});
}
}
This references two other classes, the XML annotated java classes. They are:
import java.util.List;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
#Root
public class ArrayOfScore {
#ElementList(inline=true,required=false)
private List<Score> scores;
public List<Score> getScores() {
return scores;
}
}
And:
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
#Root(name="Score")
public class Score {
#Element(name="Id",required=false)
Integer Id;
#Element(name="Name",required=false)
String Name;
#Element(name="Points",required=false)
String Points;
#Element(name="dateTime",required=false)
String dateTime;
}
With this simple model you can parse nearly any XML you encounter and get the parsing into first class objects automatically. There are similar classes for JSON such as Gson
Related
I am trying to build an app for class and am having trouble with handling data that is gathered in another thread. The data does not seems to being passed through the handlers handleMessage method.
This is my main activity
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
import android.support.constraint.ConstraintLayout;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.Buffer;
import java.util.*;
public class MainActivity extends AppCompatActivity implements BookListFragment.OnFragmentInteractionListener {
ArrayList<Book> names;
private boolean twoPane = false;
BookListFragment blf;
BookDetailsFragment bdf;
// Handler bookHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
twoPane = findViewById(R.id.container2) == null;
names = new ArrayList<Book>();
final EditText searchBar = findViewById(R.id.searchbar);
final Handler bookHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
String response = (String) msg.obj;
try{
JSONArray tmp = new JSONArray(response);
for(int i = 0; i < tmp.length(); i++){
JSONObject a = tmp.getJSONObject(i);
int id = a.getInt("book_id");
String title = a.getString("title");
Log.d("BOOK_id", a.getInt("book_id")+"");
String author = a.getString("author");
int published = a.getInt("published");
String coverUrl = a.getString("cover_url");
Book book = new Book(id,title,author,published,coverUrl);
names.add(book);
}
} catch (Exception e){
Log.d("FAIL", e.toString());
}
return false;
}
});
Thread t = new Thread(){
#Override
public void run() {
String searchString = searchBar.getText().toString();
URL bookURL;
try {
bookURL = new URL("https://kamorris.com/lab/audlib/booksearch.php?search="+searchString);
BufferedReader reader = new BufferedReader(new InputStreamReader(bookURL.openStream()));
String response = "",tmpResponse;
tmpResponse = reader.readLine();
while(tmpResponse != null){
response = response + tmpResponse;
tmpResponse = reader.readLine();
}
Log.d("Handler", response);
Message msg = Message.obtain();
msg.obj = response;
bookHandler.handleMessage(msg);
} catch (Exception e) {
Log.e("Fail", e.toString());
}
}
};
t.start();
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Thread t = new Thread(){
#Override
public void run() {
String searchString = searchBar.getText().toString();
URL bookURL;
try {
bookURL = new URL("https://kamorris.com/lab/audlib/booksearch.php?search="+searchString);
BufferedReader reader = new BufferedReader(new InputStreamReader(bookURL.openStream()));
String response = "",tmpResponse;
tmpResponse = reader.readLine();
while(tmpResponse != null){
response = response + tmpResponse;
tmpResponse = reader.readLine();
}
JSONArray bookOBJ= new JSONArray(response);
Message msg = Message.obtain();
msg.obj = bookOBJ;
bookHandler.handleMessage(msg);
} catch (Exception e) {
Log.d("Fail", e.toString());
}
}
};
t.start();
}
});
}
The code is suppose to get data from an api and then in the handleMessage method it is suppose to parse the data into a book object that contains two int and three string variables. The problem is that the handler never executes any code.
The execution should be that the debugger log should have the response string with the data from the API and then the id of every book in the JSON file, but it only has the data from the api displayed.
This question already has answers here:
What arguments are passed into AsyncTask<arg1, arg2, arg3>?
(5 answers)
Closed 3 years ago.
I am working on an Android app in which I am making a weather app. The application opens api data from a JSON and displays this information. More specifically it takes the user input of a city or zip code and adds this info to the URL for the API and then executes the URL.
MainActivity.java
package com.shanehampcsci3660.weather;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
//import static com.shanehampcsci3660.weather.GetJsonData.*;
public class MainActivity extends AppCompatActivity
{
public static TextView tempTV, jsonTV;
public EditText cityORZipET;
private Button getWeather;
public String zip, cityOrZip;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tempTV = (TextView) findViewById(R.id.tempTV);
jsonTV = (TextView) findViewById(R.id.jsonFeedTV);
cityORZipET = (EditText) findViewById(R.id.cityORZipET);
getWeather = (Button) findViewById(R.id.getWeatherButton);
//cityOrZip = cityORZipET.getText().toString();
getWeather.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
GetJsonData getJsonData = new GetJsonData();
//getJsonData.execute();
cityOrZip = cityORZipET.getText().toString();
getJsonData.execute("https://api.openweathermap.org/data/2.5/weather?q=" + cityOrZip +"&appid=x");
jsonTV.setText(cityOrZip);
/*if(cityOrZip.equals(""))
{
getJsonData.execute("https://api.openweathermap.org/data/2.5/weather?q=" + cityOrZip +"&appid=x");
}
else
{
zip = "30528";
getJsonData.execute("https://api.openweathermap.org/data/2.5/weather?q=" + zip + "&appid=x");
}*/
}
});
}
}
GetJsonData.java
package com.shanehampcsci3660.weather;
import android.os.AsyncTask;
import android.util.Log;
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;
public class GetJsonData extends AsyncTask<Void, Void, Void>
{
public String data= "", line = "", name = "";
double temp, minTemp, maxTemp;
#Override
protected Void doInBackground(Void... voids)
{
try
{
URL url = new URL("https://api.openweathermap.org/data/2.5/weather?q=30528&appid=id");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
while(line != null)
{
line = bufferedReader.readLine();
data = data + line;
}
JSONObject jsonObject = new JSONObject(data);
JSONObject main = jsonObject.getJSONObject("main");
name = jsonObject.getString("name");
temp = main.getDouble("temp");
minTemp = main.getDouble("min_temp");
maxTemp = main.getDouble("max_temp");
/*JSONObject jsonObject = new JSONObject(result);
JSONObject jsonData = new JSONObject(jsonObject.getString("main"));
String weatherInfo = jsonObject.getString("weather");
JSONArray jsonArray = new JSONArray(weatherInfo);
String description, icon, iconURI;
for(int i = 0; i < jsonArray.length(); i++)
{
JSONObject jsonData1 = jsonArray.getJSONObject(i);
description = jsonData1.getString("description");
MainActivityController.description.setText(description);
icon = jsonData1.getString("icon");
iconURI = "http://openweathermap.org/img/w/" + icon + ".png";
Picasso.get().load(iconURI).into(MainActivityController.conditionImageView);
}*/
}
catch(MalformedURLException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
catch (JSONException e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid)
{
super.onPostExecute(aVoid);
//MainActivity.jsonTV.setText(data);
MainActivity.tempTV.setText("City:\t" + name + "\tTemp:\t" + temp);
Log.d("Json Feed", name + "Temp: " + temp);
}
public static void execute(String s) {
}
}
My issue is that no matter where I put...
if(cityOrZip.equals(""))
{
getJsonData.execute("https://api.openweathermap.org/data/2.5/weather?q=" + cityOrZip +"&appid=id");
}
else
{
zip = "30528";
getJsonData.execute("https://api.openweathermap.org/data/2.5/weather?q=" + zip + "&appid=id");
}
...It will only show the data of the default Url opened in GetJsonData.java. My question is what am I doing wrong and what should I correct in order to make my app work with the user input like it should.
you are calling an GetJsonData.execute with the url that contains the client data, but it has no code in it. Looking at your current code the zip that the client inputs does not get stored into the worker class.
This is because you always use the same URL in GetJsonData class. According to question What arguments are passed into AsyncTask? your class declaration should look like:
public class GetJsonData extends AsyncTask<String, Void, YourPojo> {
#Override
protected YourPojo doInBackground(String... urls)
{
try
{
URL url = new URL(urls[0]);
...
} catch (Exception e) {
handle(e);
}
}
}
where YourPojo is a class you need to create to store all properties you need to read from JSON payload:
class YourPojo {
private String data;
private String line;
private String name;
private double temp;
private double minTemp
private double maxTemp;
// getters, setters
}
This question already has answers here:
Convert JSON String to Pretty Print JSON output using Jackson
(11 answers)
Closed 6 years ago.
I have an API in JSON , my json datas are displayed raw on my android application , i want them to be displayed in pretty print format like this
Not like this
This is my java code :
package com.example.cbmedandroid;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity implements OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.my_button).setOnClickListener(this);
}
#Override
public void onClick(View arg0) {
Button b = (Button)findViewById(R.id.my_button);
b.setClickable(false);
new LongRunningGetIO().execute();
}
private class LongRunningGetIO extends AsyncTask <Void, Void, String> {
protected String getASCIIContentFromEntity(HttpEntity entity) throws IllegalStateException, IOException {
InputStream in = entity.getContent();
StringBuffer out = new StringBuffer();
int n = 1;
while (n>0) {
byte[] b = new byte[4096];
n = in.read(b);
if (n>0) out.append(new String(b, 0, n));
}
return out.toString();
}
#Override
protected String doInBackground(Void... params) {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet("http://10.0.2.2:8000/api/horaire.json");
String text = null;
try {
HttpResponse response = httpClient.execute(httpGet, localContext);
HttpEntity entity = response.getEntity();
text = getASCIIContentFromEntity(entity);
} catch (Exception e) {
return e.getLocalizedMessage();
}
return text;
}
protected void onPostExecute(String results) {
if (results!=null) {
EditText et = (EditText)findViewById(R.id.my_edit);
et.setText(results);
}
Button b = (Button)findViewById(R.id.my_button);
b.setClickable(true);
}
}
}
How to do that ?
Thanks
You need to use a JSON library like Jackson or GSON in order to pretty print your output. For an example with Jackson take a look at the answer here.
This question already has answers here:
Sending and Parsing JSON Objects in Android [closed]
(11 answers)
Closed 7 years ago.
I am building an Android application that receives some data in JSON format. At the moment the result is very ugly. I want to display this data neatly in multiple TextViews in my application but I am not to sure how to do it. Source code below.
Main.java
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class Main extends Activity implements OnClickListener {
TextView txt1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.my_button).setOnClickListener(this);
}
#Override
public void onClick(View arg0) {
Button b = (Button)findViewById(R.id.my_button);
b.setClickable(false);
new LongRunningGetIO().execute();
}
private class LongRunningGetIO extends AsyncTask <Void, Void, String> {
protected String getASCIIContentFromEntity(HttpEntity entity) throws IllegalStateException, IOException {
InputStream in = entity.getContent();
StringBuffer out = new StringBuffer();
int n = 1;
while (n>0) {
byte[] b = new byte[4096];
n = in.read(b);
if (n>0) out.append(new String(b, 0, n));
}
return out.toString();
}
#Override
protected String doInBackground(Void... params) {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet("https://api.myjson.com/bins/363s3");
String text = null;
try {
HttpResponse response = httpClient.execute(httpGet, localContext);
HttpEntity entity = response.getEntity();
text = getASCIIContentFromEntity(entity);
} catch (Exception e) {
return e.getLocalizedMessage();
}
return text;
}
protected void onPostExecute(String results) {
if (results!=null) {
txt1 = (TextView)findViewById(R.id.textView1);
txt1.setText(results);
}
Button b = (Button)findViewById(R.id.my_button);
b.setClickable(true);
}
}
}
i use retrofit for asynchronous execution use Callback
If what u mean is how to structure the data u receive from the json then you should look into json formatting frameworks (like 'Jackson' or 'Gson' or others).
If what u mean is how to make the textual json appear neatly in a textbox, jackson also appears to have an option to print the json neatly (try this: http://www.mkyong.com/java/how-to-enable-pretty-print-json-output-jackson/ )
What about trying something like,
JSONObject jsonObject = new JSONObject(jsonString);
By the way, Volley is a good library for any kind of requests.
I am not sure what causing the request not to execute. I was trying to call a WCF Restful service in android, and I receive the error message "Request Error". Looking at the example, I don't see any reason why this example should not work. See below:
Here is the .Net Service:
[ServiceContract]
public interface ISampleService
{
[OperationContract]
[WebInvoke(
Method="POST", UriTemplate="/Login", BodyStyle= WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
string Login(string value);
}
public class SampleService : ISampleService
{
public string Login(string value)
{
string t = "";
try
{
//foreach (string s in value)
//{
// t = s;
//}
return t;
}
catch (Exception e)
{
return e.ToString();
}
}
}
Java:
package com.mitch.wcfwebserviceexample;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONStringer;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;
public class MainActivity extends Activity implements OnClickListener {
private String values ="";
Button btn;
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)this.findViewById(R.id.btnAccess);
tv = (TextView)this.findViewById(R.id.tvAccess);
btn.setOnClickListener(this);
}
#Override
public void onClick(View arg0) {
try
{
AsyncTaskExample task = new AsyncTaskExample(this);
task.execute("");
String test = values;
tv.setText(values);
} catch(Exception e)
{
Log.e("Click Exception ", e.getMessage());
}
}
public class AsyncTaskExample extends AsyncTask<String, Void,String>
{
private String Result="";
//private final static String SERVICE_URI = "http://10.0.2.2:8889";
private final static String SERVICE_URI = "http://10.0.2.2:65031/SampleService.svc";
private MainActivity host;
public AsyncTaskExample(MainActivity host)
{
this.host = host;
}
public String GetSEssion(String URL)
{
boolean isValid = true;
if(isValid)
{
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://10.0.2.2:65031/SampleService.svc/Login");
try
{
List<NameValuePair> value = new ArrayList<NameValuePair>(1);
value.add(new BasicNameValuePair("value", "123456"));
post.setEntity(new UrlEncodedFormEntity(value));
HttpResponse response = client.execute(post) ;
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line ="";
while((line = rd.readLine()) != null)
{
System.out.println(line);
}
}catch(Exception e)
{
Log.e("Error", e.getMessage());
}
}
return Result;
}
#Override
protected String doInBackground(String... arg0) {
android.os.Debug.waitForDebugger();
String t = GetSEssion(SERVICE_URI);
return t;
}
#Override
protected void onPostExecute(String result) {
// host.values = Result;
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
#Override
protected void onCancelled() {
// TODO Auto-generated method stub
super.onCancelled();
}
}
}
I finally got it to work they way that I want it to. The issue was that I was building the Array this way (see below section 1) and pass it to the JSONObject or JSONArray. I switched and build the Array using JSONArray and pass it to the JSONObject (see section 2). It works like a charm.
Section1: Wrong way to do it - (It may work this way if you were to look through the array and put them in a JSONArray. It's will be too much work when it can be done directly.)
String[][] Array = {
new String[]{"Example", "Test"},
new String[]{"Example", "Test"},
};
JSONArray jar1 = new JSONArray();
jar1.put(0, Array);
// Did not work
Section 2: The way I did it after long hours of trying and some very helpful tips and hints from #vorrtex.
**JSONArray jar1 = new JSONArray();
jar1.put(0, "ABC");
jar1.put(1, "Son");
jar1.put(2, "Niece");**
**JSONArray jarr = new JSONArray();
jarr.put(0, jar1);**
JSONArray j = new JSONArray();
j.put(0,"session");
JSONObject obj = new JSONObject();
obj.put("value", jarr);
obj.put("test", j);
obj.put("name","myName");
Log.d("Obj.ToString message: ",obj.toString());
StringEntity entity = new StringEntity(obj.toString());
Looking at the web service, and it has exactly what I was looking for.
Thanks for you help!!!!