Perform AsyncTask on Android / Posting JSON - java

I am working on an android app, and am running into some troubles with registering users. I want to post a JSON object to my server and receive one back. I can successfully create a JSON object with the right information but when I go to post it I get a NetworkOnMainThreadException or my HttpClient class returns null when it should be returning a JSONObject and I am very confident that my web server works correctly. I understand that you cannot connect to the network on the main thread and have created an HttpClient class that uses AsnycTask (although probably not correctly). I have been working on this for quite a while and would appreciate any guidance in the right direction.
//Main activity
#Override
public void onClick(View arg0) {
if(!(isEmpty(name) || isEmpty(username) || isEmpty(password) || isEmpty(email))) {
user = new JSONObject();
try {
user.put("username", username.getText().toString());
user.put("name", name.getText().toString());
user.put("email", email.getText().toString());
user.put("password", password.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
jRegister = new JSONObject();
try {
jRegister.put("apiToken", Utilities.apiToken);
jRegister.put("user", user);
Log.i("MainActivity", jRegister.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
//
HttpClient client = new HttpClient(url, jRegister);
result = client.getJSONFromUrl();
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}else {
tv.setText("");
}
}
HttpClient Class
public class HttpClient extends AsyncTask<Void, Void, JSONObject>{
private final String TAG = "HttpClient";
private String URL;
private JSONObject jsonObjSend;
private JSONObject result = null;
public HttpClient(String URL, JSONObject jsonObjSend) {
this.URL = URL;
this.jsonObjSend = jsonObjSend;
}
public JSONObject getJSONFromUrl() {
this.execute();
return result;
}
#Override
protected JSONObject doInBackground(Void... params) {
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
StringEntity se;
se = new StringEntity(jsonObjSend.toString());
// Set HTTP parameters
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
// convert content stream to a String
String resultString= convertStreamToString(instream);
instream.close();
resultString = resultString.substring(1,resultString.length()-1); // remove wrapping "[" and "]"
JSONObject jsonObjRecv = new JSONObject(resultString);
// Raw DEBUG output of our received JSON object:
Log.i(TAG,"<JSONObject>\n"+jsonObjRecv.toString()+"\n</JSONObject>");
return jsonObjRecv;
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(JSONObject jObject) {
result = jObject;
}
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}

I understand that you cannot connect to the network on the main thread
and have created an HttpClient class that uses AsnycTask (although
probably not correctly).
You are right you have not implemented it the right way.
In your onClick events (still on Main thread) you performed a network activity causing the error:
HttpClient client = new HttpClient(url, jRegister);
result = client.getJSONFromUrl();
Instead you should run the network operation inside of the AsnycTask
public class GetJsonTask extends AsyncTask<Void, Void, JSONObject >{
private String URL;
private JSONObject jsonObjSend;
public GetJsonTask(String URL, JSONObject jsonObjSend) {
this.URL = URL;
this.jsonObjSend = jsonObjSend;
}
#Override
protected JSONObject doInBackground(Void... params) {
JSONObject jsonObjRecv;
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
StringEntity se;
se = new StringEntity(jsonObjSend.toString());
// Set HTTP parameters
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
// convert content stream to a String
String resultString= convertStreamToString(instream);
instream.close();
resultString = resultString.substring(1,resultString.length()-1); // remove wrapping "[" and "]"
jsonObjRecv = new JSONObject(resultString);
// Raw DEBUG output of our received JSON object:
Log.i(TAG,"<JSONObject>\n"+jsonObjRecv.toString()+"\n</JSONObject>");
}
}
catch (Exception e) {
e.printStackTrace();
}
return jsonObjRecv;
}
protected void onPostExecute(JSONObject result) {
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}else {
tv.setText("");
}
}
}
Then you call your async in onclik method like this:
public void onClick(View arg0) {
//.......
GetJsonTask client = new GetJsonTask(url, jRegister);
client.execute();
}

One problem in your code is that your expectations of AsyncTask aren't quite right. In particular this function:
public JSONObject getJSONFromUrl() {
this.execute();
return result;
}
AsyncTask runs the code in the doInBackground() function in a separate thread. This means that once you call execute() you have two parallel lines of execution. You end up with what's called a Race Condition. When you reach the return result line, a couple of things can be happening:
doInBackground() hasn't run and therefore result is still has the default value. In this case null.
doInBackground() can be in the middle of the code. In your particular case because it doesn't modify result then this doesn't affect you much. But it could be on any line (or middle of a line sometimes if operations aren't atomic) when that return happens.
doInBackground() could've finished, but since onPostExecute() runs on the UI thread it has to wait until your onClick handler is finished. By the time onPostExecute() has a chance to run onClick already tried to update tv with whatever it was that getJSONFromUrl returned, most likely null.
The way to set up tasks with AsyncTask is to give it the information it needs to do it's work, start it up with execute, and since you can't know how long it will take to complete, let it handle the finishing steps of the task.
This means that after calling execute you don't wait around for it's result to update views (like in your case), but rather rely on the AsyncTask's onPostExecute or related methods to take over the next steps.
For your case this would mean that your onPostExecute should look something like:
protected void onPostExecute(JSONObject result) {
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}

Related

Show progress bar while downloading JSON - Android

I am downloading a very huge JSON and it takes a lot of time.
I want to show the percentage of data I have downloaded.
I searched and found how to display progress if downloading a file but not JSON.
Here is how I am downloading JSON
private String getStringFromURL(String url) {
String string = null;
try {
HttpClient client = new DefaultHttpClient();
url = url.replace(" ", "%20");
url = url.replace("|", "%7C");
HttpGet get = new HttpGet(url);
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
String result = EntityUtils.toString(response.getEntity(),
HTTP.UTF_8);
if (result.toLowerCase().contains("invalid"))
return null;
result = result.replace("\r", "");
result = result.replace("\n", "").replace("\t", "\\t")
.replace("\b", "\\b").replace("\f", "\\f")
.replace("&", "\\&").replace("\'", "\\'")
.replace(";", "\\;").replace("?", "\\?")
.replace("*", "\\*");
string = result;
}
} catch (Exception e) {
e.printStackTrace();
}
return string;
}
You better to use AsyncTask to download data. There is a sample code below. I did not test it but it should work.
private class FetchJsonTask extends AsyncTask<Void, Void, String> {
private ProgressDialog progressDialog;
private Context context;
public FetchJsonTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
// set up progress dialog
progressDialog = new ProgressDialog(context);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Please wait...");
// show it
progressDialog.show();
}
#Override
protected String doInBackground(Void... params) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String jsonStr = null;
try {
// Construct the URL somehow
URL url = createURL();
// Create the request to MuslimSalat.com, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
jsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the data, there's no point in attemping
// to parse it.
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return jsonStr;
}
#Override
protected void onPostExecute(String jsonString) {
// jsonString is your result use it somehow.
Log.d(LOG_TAG, "Json result: " + jsonString);
// dismiss the progress because downloading process is finished.
progressDialog.dismiss();
}
}
You can call it from your activity, fragment etc.
FetchJsonTask fetchJsonTask = new FetchJsonTask(context);
fetchJsonTask.execute();

What is the most efficient way on Android to call HTTP Web API calls that return a JSON response?

I'm the perfectionist type, I already got web API calls working fine with Google Places API (just as an example), but I feel it's sometimes slow or maybe I'm not doing it right. Some blogs are saying I should use AndroidHttpClient, but I'm not, should I ?
The web API calls i'm using return json and I don't run them on the UI thread, hence using AsyncTask (is AsyncTask the most efficient way to run on background thread or should I use something else ?)
Please see my code and tell me how could it be more efficient in anyway
public static class NearbySearchRequest extends AsyncTask<String, Void, JSONObject>
{
Exception mException = null;
#Override
protected void onPreExecute()
{
super.onPreExecute();
this.mException = null;
}
#Override
protected JSONObject doInBackground(String... params)
{
StringBuilder urlString = new StringBuilder();
urlString.append("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
urlString.append("key=").append(Constants.GOOGLE_SIMPLE_API_KEY);
urlString.append("&location=").append(params[0]);
urlString.append("&sensor=").append("true");
urlString.append("&language=").append("en-GB");
urlString.append("&name=").append(params[1]);
urlString.append("&rankby=").append("distance");
LogHelper.Log(urlString.toString());
HttpURLConnection urlConnection = null;
URL url = null;
JSONObject object = null;
try
{
url = new URL(urlString.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.connect();
InputStream inStream = null;
inStream = urlConnection.getInputStream();
BufferedReader bReader = new BufferedReader(new InputStreamReader(inStream));
String temp, response = "";
while ((temp = bReader.readLine()) != null)
response += temp;
bReader.close();
inStream.close();
urlConnection.disconnect();
object = (JSONObject) new JSONTokener(response).nextValue();
}
catch (Exception e)
{
this.mException = e;
}
return (object);
}
#Override
protected void onPostExecute(JSONObject result)
{
super.onPostExecute(result);
if (this.mException != null)
ErrorHelper.report(this.mException, "Error # NearbySearchRequest");
}
}
The Http engine you're using seems the best choice. Actually any other 3-rd party engines are based either on Apache, either on HttpUrlConnection. I prefer to use Spring for Android as that API provide an abstraction over Http Engine and you don't really need to care how about what API to use based on API level. Or you can use Volley - a very fashionable library.
I would touch however some of your code:
What if there is an exception while reading the stream? Then the stream remains open and also the connection. So I would suggest to have a finally block where the streams and connection is closed no matter if you get an exception or not:
HttpURLConnection urlConnection = null;
URL url = null;
JSONObject object = null;
InputStream inStream = null;
try {
url = new URL(urlString.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.connect();
inStream = urlConnection.getInputStream();
BufferedReader bReader = new BufferedReader(new InputStreamReader(inStream));
String temp, response = "";
while ((temp = bReader.readLine()) != null) {
response += temp;
}
object = (JSONObject) new JSONTokener(response).nextValue();
} catch (Exception e) {
this.mException = e;
} finally {
if (inStream != null) {
try {
// this will close the bReader as well
inStream.close();
} catch (IOException ignored) {
}
}
if (urlConnection != null) {
urlConnection.disconnect();
}
}
JSON parsing: you're using the Android standard way of parsing JSON, but that's not the fastest and easiest to work with. GSON and Jackson are better to use. To make a comparison when it comes for JSON parsers, I would go for Jackson. Here's another SO topic on this comparison.
Don't concatenate strings like that as concatenating strings will create each time another string. Use a StringBuilder instead.
Exception handling (this is anyway a long-debate subject in all programming forums). First of all you have to log it (Use Log class not System.out.printXXX). Then you need to either inform the user: either you toast a message, either you show a label or notification. The decision depends on the user case and how relevant is the call you're making.
These are the topics I see in you code.
EDIT I realize I didn't answer this: is AsyncTask the most efficient way to run on background thread or should I use something else?
The short answer I would give is: if you're supposed to perform a short time lived request, then AsyncTask is perfect. However, if you need to get some data and display it - but you don't want to worry about whether to download again if the screen is rotated and so on, I would strongly recommend using an AsyncTaskLoader and Loaders in general.
If you need to download some big data, then either you use an IntentService or, for heavy-weight operations, DownloadManager.
Enjoy coding!
------Create a Service Handler Class to your Project--------
public class ServiceHandler {
static String response = null;
public final static int GET = 1;
public final static int POST = 2;
public ServiceHandler() {
}
/*
* Making service call
* #url - url to make request
* #method - http request method
* */
public String makeServiceCall(String url, int method) {
return this.makeServiceCall(url, method, null);
}
/*
* Making service call
* #url - url to make request
* #method - http request method
* #params - http request params
* */
public String makeServiceCall(String url, int method,
List<NameValuePair> params) {
try {
// http client
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
// Checking http request method type
if (method == POST) {
Log.e("in POST","in POST");
HttpPost httpPost = new HttpPost(url);
// adding post params
if (params != null) {
Log.e("in POST params","in POST params");
httpPost.setEntity(new UrlEncodedFormEntity(params));
}
Log.e("url in post service",url);
httpResponse = httpClient.execute(httpPost);
} else if (method == GET) {
// appending params to url
Log.e("in GET","in GET");
if (params != null) {
Log.e("in GET params","in GET params");
String paramString = URLEncodedUtils
.format(params, "utf-8");
url += "?" + paramString;
}
Log.e("url in get service",url);
HttpGet httpGet = new HttpGet(url);
httpResponse = httpClient.execute(httpGet);
}
httpEntity = httpResponse.getEntity();
response = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
public String makeServiceCallIMAGE(String url, int method,
List<NameValuePair> params) {
try {
// http client
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
// Checking http request method type
if (method == POST) {
HttpPost httpPost = new HttpPost(url);
// adding post params
if (params != null) {
httpPost.setEntity(new UrlEncodedFormEntity(params));
}
httpResponse = httpClient.execute(httpPost);
} else if (method == GET) {
// appending params to url
if (params != null) {
String paramString = URLEncodedUtils
.format(params, "utf-8");
url += "?" + paramString;
}
HttpGet httpGet = new HttpGet(url);
httpResponse = httpClient.execute(httpGet);
}
httpEntity = httpResponse.getEntity();
response = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
}
--------------AsyncTask For Login------------------
public class Login_Activity extends ActionBarActivity {
//Internet Service
NetworkConnection nw;
ProgressDialog prgDialog;
Boolean netConnection = false;
//
//Login API
String loginURL ="url";
//
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
nw = new NetworkConnection(getApplicationContext());
prgDialog = new ProgressDialog(this);
// Set Cancelable as False
prgDialog.setCancelable(false);
new LoginOperation().execute();
}
private class LoginOperation extends AsyncTask<String, Void, Void> {
String status, message;
#Override
protected void onPreExecute() {
// Set Progress Dialog Text
prgDialog.setMessage("Logging...");
prgDialog.show();
}
#Override
protected Void doInBackground(String... urls) {
if(nw.isConnectingToInternet() == true)
{
try
{
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("method", "ClientesLogin"));
nameValuePairs.add(new BasicNameValuePair("Email", str_Email));
nameValuePairs.add(new BasicNameValuePair("Senha", str_Password));
ServiceHandler sh = new ServiceHandler();
String response = sh.makeServiceCall(loginURL, ServiceHandler.GET,
nameValuePairs);
Log.e("response", response);
JSONObject js = new JSONObject(response);
status = js.getString("status");
Log.e("status",status);
if(status.contains("Fail"))
{
message = js.getString("message");
}
/*else
{
JSONObject jslogin=js.getJSONObject("user_list");
for (int i = 0; i < jslogin.length(); i++) {
}
}*/
}catch(Exception ex){
}
netConnection = true;
}else
{
netConnection = false;
}
return null;
}
#Override
protected void onPostExecute(Void result) {
prgDialog.dismiss();
if(netConnection == false)
{
Toast toast = Toast.makeText(getApplicationContext(),"Internet is not available. Please turn on and try again.", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
else
{
if(status.contains("Success"))
{
Toast toast = Toast.makeText(getApplicationContext(), "Login Successful", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
Intent i=new Intent(Login_Activity.this,home_page_activity.class);
startActivity(i);
}
else{
Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
super.onPostExecute(result);
}
}
}
---------------Network Connection class---------------------
public class NetworkConnection {
Context context;
public NetworkConnection(Context context){
this.context = context;
}
public boolean isConnectingToInternet(){
ConnectivityManager connectivity = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null)
{
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null)
for (int i = 0; i < info.length; i++)
if (info[i].getState() == NetworkInfo.State.CONNECTED)
{
return true;
}
}
return false;
}
}
JSONArray main1 = js.getJSONArray("Test 1");
for (int i = 0; i < main1.length(); i++) {
JSONObject jsonObject = main1.getJSONObject(i);

reading JSON data from URL

I am trying to parse some JSON data, but my app doesn't do anything because i can't seem to get any response from URL, i tried to open URL connection in few different ways, but it's still the same. for Example :
urlMy=new URL(string);
URLConnection tc = urlMy.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
tc.getInputStream()));
String line=in.readLine();
doesn't return anything, it even dismisses everything in my function written below that code.
Or
urlMy=new URL(examp);
InputStream inputStream = urlMy.openConnection().getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
BufferedReader bR = new BufferedReader(reader);
the same thing. This function is called and like it never happend, every function after this one executes, so it's not in the endless loop, but every bit of code in this function after this example code is ignored. if i remove this code for reading url, everthing else works.
Try to use AsyncTask,try something like:
class MyAsyncTask extends AsyncTask<String, String, Void> {
private ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
InputStream inputStream = null;
String result = "";
protected void onPreExecute() {
progressDialog.setMessage("Downloading your data...");
progressDialog.show();
progressDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface arg0) {
MyAsyncTask.this.cancel(true);
}
});
}
#Override
protected Void doInBackground(String... params) {
String url_select = "http://yoururlhere.com"
ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
try {
// Set up HTTP post
// HttpClient is more then less deprecated. Need to change to URLConnection
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select);
httpPost.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
// Read content & Log
inputStream = httpEntity.getContent();
} catch (UnsupportedEncodingException e1) {
Log.e("UnsupportedEncodingException", e1.toString());
e1.printStackTrace();
} catch (ClientProtocolException e2) {
Log.e("ClientProtocolException", e2.toString());
e2.printStackTrace();
} catch (IllegalStateException e3) {
Log.e("IllegalStateException", e3.toString());
e3.printStackTrace();
} catch (IOException e4) {
Log.e("IOException", e4.toString());
e4.printStackTrace();
}
// Convert response to string using String Builder
try {
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream, "iso-8859-1"), 8);
StringBuilder sBuilder = new StringBuilder();
String line = null;
while ((line = bReader.readLine()) != null) {
sBuilder.append(line + "\n");
}
inputStream.close();
result = sBuilder.toString();
} catch (Exception e) {
Log.e("StringBuilding & BufferedReader", "Error converting result " + e.toString());
}
} // protected Void doInBackground(String... params)
protected void onPostExecute(Void v) {
//parse JSON data
try{
JSONArray jArray = new JSONArray(result);
for(i=0; i < jArray.length(); i++) {
JSONObject jObject = jArray.getJSONObject(i);
String name = jObject.getString("name");
String tab1_text = jObject.getString("tab1_text");
int active = jObject.getInt("active");
} // End Loop
this.progressDialog.dismiss();
} catch (JSONException e) {
Log.e("JSONException", "Error: " + e.toString());
} // catch (JSONException e)
} // protected void onPostExecute(Void v)
} //class MyAsyncTask extends AsyncTask<String, String, Void>
In the last Google I/O, Google released a new library called Volley. It's fast for HTTP requests, very easy to use and you can set it up to return JSONObjects ready for parsing. https://developers.google.com/events/io/sessions/325304728

android use asynctask to parse json

I am working on android application and I need to parse my json object with data. How you can see I create JSONParser class and try to use asynctask but there is something wrong and I can't understand where is the problem. Every time I use it resultJSON is null. Hope that you can give me an advice!
public class JSONParser {
private String resultJSON;
public JSONArray getJSON(String url) throws JSONException {
Parser parser = new Parser();
parser.execute(url);
return json;
}
private class Parser extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
for (String url : urls) {
StringBuilder builder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
resultJSON = builder.toString();
} else {
Log.e(JSONParser.class.toString(), "Failed to download file");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultJSON;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
json = new JSONArray(result);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
Why don't you JSONArray json = new JSONArray(resultJSON); do this on post execute method of async task .
And i will not suggest varevarao way , as it will create extra burden of one thread .
You should use the get() method of the AsyncTask class to retrieve the result of the task. It waits for the task to complete and gets the result (which means it'd be best if you enclose it within a separate thread with a progress dialog or just a background thread).
public JSONArray getJSON(String url) throws JSONException {
Parser parser = new Parser();
parser.execute(url);
resultJSON = parser.get(); // Probably put this in a Thread to avoid spending too much time waiting for a result on the main thread
JSONArray json = new JSONArray(resultJSON);
return json;
}
The problem is fixed. It's an awful workaround but it works. Add this line
while(json==null) {}
after calling the execute method.

Getting data from PHP in Android

I've seen several tutorials for this, but they're all older than the Android update that prevents network calls in the main thread. I tried moving the code that called it to a RetrieveFeedTask, but that didn't help me, because I then had no way to get the data in my main thread. Here's what I did:
class RetrieveFeedTask extends AsyncTask <String, Void, String>
{
private Exception exception;
private String doInBackground()
{
String returnString = "sample";
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
//http post
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost/sample_array.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection"+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
sb = new StringBuilder();
sb.append(reader.readLine() + "\n");
String line="0";
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
//paring data
int step_num;
String description;
try{
jArray = new JSONArray(result);
JSONObject json_data=null;
for(int i=0;i<jArray.length();i++){
json_data = jArray.getJSONObject(i);
step_num=json_data.getInt("step_num");
description=json_data.getString("description");
}
}
catch(JSONException e1){
Toast.makeText(getBaseContext(), "No step found" ,Toast.LENGTH_LONG).show();
} catch (ParseException e1) {
e1.printStackTrace();
}
//System.out.println(result);
return result;
}
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
return null;
}
}
Then in the main thread, I did this:
AsyncTask<String, Void, String> returnString = new RetrieveFeedTask().execute();
So how do I get that information to use in the main thread?
You're almost ok with that but there are 2 errors:
You're overloading the doInBackground method that could never get called.
implement your stuff inside the "currently" empty doInBackground implementation.
If you want to get your data back on your main thread you can:
use the runOnUiThread Method
create an Anonymous Inner Class inside your activity that will extend your asynctask and overrides the onPostExecute method. ( which runs on the ui thread )
:)
You can make one web-service that returns data you need in JSON format. Put that on to your server.
Now call that web-service using android. This way You can get data from PHP to android
Implement your current code in empty doInBackground block
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
return null;
}
return string from above method, will be received in onPostExecute method, that you need to implement in your code too, which is actually missing at present.

Categories