i am trying to parse a jsonObject, but i cant get the result out of doInBackground into onPostExecute
Here is my AsyncTask code:
private class GetContacts extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(MyActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
String auth2 = jsonObj.getString("auth");
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
#Override
protected void onPostExecute(Void auth2) {
super.onPostExecute(auth2);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
Toast.makeText(getApplicationContext(), "String retrived:" + auth2, Toast.LENGTH_SHORT).show();
}
}
I know its propably because i have return null there, but when i make return string then i get error.
I know in fact that jsonStr holds json data, i can see it in log:
Response:﹕ > {"user_info":{"auth":0}}
I put this code together from tutorials, thats why i dont completly understand it.
My goal is to see if auth is 0 or 1.
cant get the result out of doInBackground into onPostExecute
To return auth2 String from doInBackground :
1. Change return type of doInBackground method from Void to String:
#Override
protected String doInBackground(Void... arg0) {
}
2. Change AsyncTask last generic type from Void to String :
private class GetContacts extends AsyncTask<Void, Void, String>
3. Return auth2 from doInBackground :
String auth2 = jsonObj.getString("auth");
return auth2;
4. Change onPostExecute parameter type from Void to String :
#Override
protected void onPostExecute(String auth2) {
super.onPostExecute(auth2);
//...
Toast.makeText(getApplicationContext(),
"String retrived:" + auth2, Toast.LENGTH_SHORT).show();
}
read the documentation:
http://developer.android.com/reference/android/os/AsyncTask.html
private class GetContacts extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... arg0) {
...
return "askdjalskdj";
}
#Override
protected void onPostExecute(String auth2) {
Log.i("Output", auth2);
}
}
See the params I have set in the Generic implementation of Asynctask , see the defined return value from doInBackground and the Parameter type of onPostExecute
AsyncTask's generic types The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the
background computation.
Result, the type of the result of the
background computation.
Not all types are always used by an
asynchronous task. To mark a type as unused, simply use the type Void:
private class MyTask extends AsyncTask { ... }
Related
In the next code I can not make the toast message inside the doInBackground method jump.
When I delete this line, the writing of the "error" string into the edittext performed fine.
What am I doing wrong?
private class Verify extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
username = etusername.getText().toString();
password = etpass.getText().toString();
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("username", username));
postParameters.add(new BasicNameValuePair("password", password));
String response = null;
String result;
try {
response = CustumHttpClient.executeHttpPost(url_verify_detials, postParameters);
result = response.toString();
result = result.replaceAll("\\s+", "");
if (!result.equals("0")) {
Intent in = new Intent(MainActivity.this, danpage.class);
startActivity(in);
} else {
Toast.makeText(getApplicationContext(), "this is my Toast message!!", Toast.LENGTH_LONG)
.show();
etusername.setText("Error");
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
You can't place any code which does anything to the user interface inside the doInBackground method. If you want to show your toast you will need to return a result to onPostExecute and deal with it there.
How do you return a result to onPostExecute? In your class definition the third parameter inside the <> is the type that you will want to return in the onPostExecute method so you declaration will look like
private class Verify extends AsyncTask<Void, Void, String>
and you onPostExecute will look like
protected void onPostExecute(String result) {
Please see the reference for a good example. http://developer.android.com/reference/android/os/AsyncTask.html
You can use publishProgress and onProgressUpdate to make a Toast:
private static final int ERROR = -1;
...
try {
response = CustumHttpClient.executeHttpPost(url_verify_detials, postParameters);
result = response.toString();
result = result.replaceAll("\\s+", "");
if (!result.equals("0")) {
Intent in = new Intent(MainActivity.this, danpage.class);
startActivity(in);
} else {
//Toast.makeText(getApplicationContext(), "this is my Toast message!!", Toast.LENGTH_LONG)
// .show();
//etusername.setText("Error");
publishProgress(ERROR);
}
} catch (Exception e) {
}
...
#Override protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (values[0]==ERROR){
Toast.makeText(MainActivity.this, "this is my Toast message!!", Toast.LENGTH_LONG)
.show();
etusername.setText("Error");
}
}
You must use runOnUIThread method to execute this code.
You must execute ui methods in that thread.
Yeap ... toast has to be displayed on the UI thread. When you don't return a result from doInBackground you can return a Boolean instead and use it in onPostExecute to show your Toast. onPostExecute is executed on the UI thread. runOnUIThread is also a solution ...
I have been using this code for the last few days and up until today it has been working perfectly, but for some reason the Async task has stopped calling the doInBackground method. I have attempted the solution suggested here Android SDK AsyncTask doInBackground not running (subclass) but I just get the same result. The onPreExecute method gets called but then I am just left with the loading dialog. Has anybody experienced anything similar to this. I have included a copy of my code. MyAsncTask is executed as follows;
new MyAsyncTask().execute(email, password);
private class MyAsyncTask extends AsyncTask<String, Void, JSONObject>
{
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
Log.v(tag, "onPreExecute");
super.onPreExecute();
pDialog = new ProgressDialog(SignInPageActivity.this);
pDialog.setMessage("Logging in...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected JSONObject doInBackground(String... params) {
Log.v(tag, "doInBackground");
CustomerFunctions userFunction = new CustomerFunctions();
if (params.length != 2)
return null;
JSONObject json = userFunction.loginUser(params[0], params[1]);
return json;
}
#Override
protected void onPostExecute(JSONObject json)
{
Log.v(tag, "onPostExecute");
try {
if (json != null && json.getString(KEY_SUCCESS) != null) {
signInError.setText("");
String res = json.getString(KEY_SUCCESS);
if(Integer.parseInt(res) == 1){
// user successfully logged in
// Store user details in SQLite Database
DatabaseHandler databaseHandler = new DatabaseHandler(getApplicationContext());
JSONObject json_user = json.getJSONObject("customer");
// Clear all previous data in database
CustomerFunctions userFunction = new CustomerFunctions();
userFunction.logoutCustomer(getApplicationContext());
databaseHandler.addUser(json.getString(KEY_UID), json_user.getString(KEY_FIRST_NAME), json_user.getString(KEY_LAST_NAME), json_user.getString(KEY_EMAIL), json_user.getString(KEY_CURRENT_STAMPS), json_user.getString(KEY_TOTAL_STAMPS), json_user.getString(KEY_REWARDS_AVAILABLE), json_user.getString(KEY_REWARDS_CLAIMED), json_user.getString(KEY_CREATED_AT));
// Launch Dashboard Screen
Intent main = new Intent(getApplicationContext(), MainActivity.class);
// Close all views before launching Dashboard
// dismiss the dialog once done
pDialog.dismiss();
main.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(main);
// Close Registration Screen
finish();
}else{
// Error in login
signInError.setText("Incorrect username/password");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
try extending like this
private class MyAsyncTask<Params, Void, JSONObject> extends AsyncTask<Params, Void, JSONObject>
and use #Override for doInBackground
I have implemented an AsyncTask to get values of a web service and store them into an array, but something I am doing wrong because it says that "Invalid index 0, size is 0". The object "dia" is not well created. Here is my code:
private class GetValue extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
metereologia = new ArrayList<DiaTemperatura>();
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
eventos = jsonObj.getJSONArray("list");
// looping through All Contacts
for (int i = 0; i < eventos.length(); i++) {
JSONObject c = eventos.getJSONObject(i);
JSONObject temp = c.getJSONObject(TAG_TEMP);
String max = temp.getString(TAG_MAX);
String min = temp.getString(TAG_MIN);
String humedad = c.getString(TAG_HUMIDITY);
JSONObject weather = c.getJSONObject(TAG_WEATHER);
//String main = weather.getString(TAG_MAIN);
//String description = weather.getString(TAG_DESCRIPTION);
DiaTemperatura dia= new DiaTemperatura();
dia.setMyText(max);
metereologia.add(dia);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
TextView mitext = (TextView) getView().findViewById(R.id.temperatura);
mitext.setText(metereologia.get(0).getMyText());
}
}
It looks like you must be declaring metereologia outside your AsyncTask, then initialising and populating it in the task. This is not quite the correct way to use it. Your AsyncTask should return the result of its computation. You'll need to declare your task as:
private class GetValue extends AsyncTask<Void, Void, List<DiaTemperatura>> {
...
#Override
protected List<DiaTemperatura> doInBackground(Void... arg0) {
List<DiaTemperatura> metereologia = new ArrayList<DiaTemperatura>();
...
return metereologia;
}
and thus onPostExecute becomes:
#Override
protected void onPostExecute(List<DiaTemperatura> metereologia) {
I think that's right, it's off the top of my head...
Your error must be in the line mitext.setText(metereologia.get(0).getMyText()); Its will go for finding the value at the index 0 in your metereologia which its is not getting.
You can not directly set the value of your whole arraylist in such a way. You need to loop for the value whichever you want to set in your TextView.
There is nothing in the metereologia so when you try to get it with (metereologia.get(0).getMyText(), it results in an error, "Invalid index 0, size is 0".
1) For doing check work -
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
TextView mitext = (TextView) getView().findViewById(R.id.temperatura);
String content = "";
if(metereologia.size() == 0)
{
//a check that your metereologia size is 0.
}
for(int i=0;i<metereologia.size();i++)
content = content + metereologia.get(i).getMyText();
mitext.setText(content);
}
}
2) To get the value right-
More convenient way is to return the object metereologia from background and pass it to postExecute method and then process.This is explained by #dave.c.
protected void onPostExecute(List<DiaTemperatura> metereologia) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
TextView mitext = (TextView) getView().findViewById(R.id.temperatura);
String content = "";
if(metereologia.size() == 0)
{
//a check that your metereologia size is 0.
}
for(int i=0;i<metereologia.size();i++)
content = content + metereologia.get(i).getMyText();
mitext.setText(content);
}
}
I am trying to use the json object outside of the Async task but my class doesn't recognize it.
How do I pass the JSONObject to the outside of the Async task?
The only thing I could find was trying to use onProgressUpdate() to pass the object but I tried implementing and the object would come up blank :(.
Any help would be appreciated, thank you.
Here is my class:
public class NewHomepage extends Activity {
public static String url = "http://www.alkouri.com/android/SQL.php?username=";
public static String usernamefromlogin;
public static TextView errorchecking;
public static JSONArray user = null;
//JSON Node Names
public String TAG_USER = "users";
public String TAG_FIRST = "first";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.reshomepage);
//get data from previous screen
Intent intent = getIntent();
getIntent().getExtras();
//convert intent (intent) to string called "usernamefromlogin"
//error checking in log cat to see value of "usernamefromlogin"
usernamefromlogin = intent.getExtras().getString("username2");
Log.d("log usernamefromlogin", usernamefromlogin);
//take the string "url" and add string "usernamefromlogin" after it
//error checking in log cat to see value of url5
String url5 = url.concat(usernamefromlogin);
Log.d("log url5", url5);
//start asynch task
class PostTask2 extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}//end PreExecute
#Override
protected String doInBackground(String... params) {
//pass url from outside class to inside this class
String url5 = params[0];
//Creating new JSON Parser
JSONParser jParser = new JSONParser();
// Getting JSON from URL
JSONObject json = jParser.getJSONFromUrl(url5);
return null;
}//end doInBackground
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}//end onProgressUpdate
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}//end onPostExecute
}//end Async task
//execute the Async task
new PostTask2().execute(url5);
}//end oncreate
#Override
public void onBackPressed() {
// do nothing on back press
}
}//end class
You have to pull your asynctask out of your onCreate method and insert it as a nested class in NewHomepage.
Now, you can return a JSONObject from doInBackground() as shown in the code below. Note the AsncTask.
This is nice to learn something (the hard way) about activity life-cycle and memory leaks (I'm serious, try it, just for practice sake). For a real application however i'd highly recommend a Rest client library like Volley.
public class NewHomepage extends Activity {
// ... your activity code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new PostTask2().execute(url5);
}
class PostTask2 extends AsyncTask<String, String, JSONObject> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}//end PreExecute
#Override
protected String doInBackground(String... params) {
//pass url from outside class to inside this class
String url5 = params[0];
//Creating new JSON Parser
JSONParser jParser = new JSONParser();
// Getting JSON from URL
JSONObject json = jParser.getJSONFromUrl(url5);
return json;
}//end doInBackground
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}//end onProgressUpdate
#Override
protected void onPostExecute(JSONObject result) {
// HERE, this is running on the main thread.
// You can do whatever you need to do with your JSONObject.
// Maybe call setData(result) but be careful, the user might have left this activty already!
// And the View might have been already destroyed, so watchout for null-pointer-exceptions
}//end onPostExecute
}
}
You need to put AsyncTask calss outside the onCreate method and call it from inside onCreate method.
P.S. However, as in the comment, post your json response and tell us what you want to parse from the response. On top of that, you need to use HTTP or Rest Client to query the server and get response.
EDIT
To know how you can make a request to server, go through this tutorial or you may also go through this tutorial.
You can return the JSONObject in your onPostExecute as below:
class PostTask2 extends AsyncTask<String, String, JSONObject> {
..............................
#Override
protected String doInBackground(String... params) {
//pass url from outside class to inside this class
String url5 = params[0];
//Creating new JSON Parser
JSONParser jParser = new JSONParser();
// Getting JSON from URL
JSONObject json = jParser.getJSONFromUrl(url5);
return json;
}//end doInBackground
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}//end onProgressUpdate
#Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
}//end onPostExecute
}//end Async task
I want to parse JSON every few seconds. My idea is by constantly parsing it to see if there are some changes in it and if there are to get them and update my views (mostly TextViews). I have a Fragment, called MyFragment. In its onCreateView I am executing the following: new MyTask().execute(myJSONUrl);. Some code:
class MyTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
//getJSONString(String url) - my method for getting the JSON from URL
return getJSONString(params[0]);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result == null || result.length() == 0) {
Log.w(TAG," JSON IS **null** ");
Toast.makeText(getActivity().getApplicationContext(), "JSON IS NULL", Toast.LENGTH_SHORT).show();
} else {
try{
JSONObject root = new JSONObject(result);
// Here i get what i need from the JSONObject and everything works fine.
} catch (Exception e) {
e.printStackTrace();
}
}
Now how to parse the JSON from URL every n seconds? I have tried using ScheduledExecutorService, Timer and Thread but nothing seems to work. Thanks in advance :-)
When you really throw the battery concerns out of the window:
Change class MyTask extends AsyncTask<String, Void, String> to class MyTask extends AsyncTask<String, String, Void>
Do the following:
protected String doInBackground(String... params) {
//getJSONString(String url) - my method for getting the JSON from URL
while(isCancelled() == false) {
try {
Thread.sleep(1000* 5); // only do this every 5 seconds.
} catch (InterruptException ex) {}
publishResult(getJSONString(params[0]));
}
}
public void onResultPublished(String result) {
// stuff that happened in onResult before...
}
You emit strings as a result and handle it in onResultPublished (this method is executed on the UI thread so it's safe to modify ui here).
Don't forget to cancel the asynctask.