I can't explain why onPostExecute is not being called in my code. I have successfully used almost this exact code with a different app before. It prints 'onPreExecute' and the successful result of the JSON fetch from doInBackground just before return result; but then onPostExecute doesn't print anything - with the super call or not - and moreover doesn't return my string to the UI thread. Any ideas?
public class PrivateLoadFromServer extends AsyncTask<String, Integer, String> {
InputStream is = null;
String result = null;
String error_text="";
JSONObject j = null;
String url;
SQLiteOpenHelper helper;
CustomActivity activity;
private Context context;
private ProgressDialog dialog;
private int count;
String employee;
String text;
public PrivateLoadFromServer(CustomActivity activity,String employee,String url){
this.url=url;
this.employee=employee;
this.activity=activity;
}
#Override
protected void onPreExecute() {
system.out.println("onPreExecute");
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
System.out.println("onPostExecute");
activity.setJSONResult(result);
/*
if(result!=null){
System.out.println("Task reported successful");
taskHandler.taskSuccessful(this.result);
activity.setJSONResult(this.result);
} else {
taskHandler.taskFailed();
}
*/
//return;
}
#Override
protected String doInBackground(String... params) {
System.out.println("Running aSyncTask");
// Successful code to get JSON result string from server omitted.
System.out.println("Raw at doInBackground: " + result);
return result;
EDIT: Should've posted this originally, I call it as an inner class in CustomActivity like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
helper=new DBHelper(this);
loadBasicData();
}
private void loadBasicData() {
// If you can encode all of these into one JSON Object, cool.
String url="*****" //Omitted URL.
String employee=null;
PrivateLoadFromServer syncTask = new PrivateLoadFromServer(this,employee,url);
syncTask.execute();
try {
syncTask.get(15000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("JSONResult at Activity:"+jsonResult); // jsonResult is null
}
}
public void setJSONResult(String result){
System.out.println("setJSONResult"+result);
this.jsonResult=result; // jsonResult is a field in the Activity.
}
Because you are calling get, the JSON result is also returned from this method (see the source code of AsyncTask.java. So you can call your method directly on the output.
try {
setJSONResult(syncTask.get(15000, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
Check if your are explicitly cancelling AsyncTask somewhere in the code before it could postExecute.
onPostExecute() is called on the main UI thread. If its not getting called, it means your UI thread is blocked doing something else.
Related
I'm trying to implement an asynchronous access to internet using AsyncTask, but in log cat PID and TID of my logging are the same, because AsyncTask doesn't create a parallel queue, so my app crashes with a NetworkOnMainThreadException.
Here's my subclass code :
class BL_SimpleAsyncTask extends AsyncTask<Void, Void, Void> {
String requestServer;
HashMap<String, String> postRequestBody;
//------------------------// answer from http client
static DefaultHttpClient sharedClient = null;
boolean isPostRequest;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
System.out.println("bg started");
if (sharedClient == null) {
sharedClient = new DefaultHttpClient();
}
HttpPost post = new HttpPost(requestServer);
String postBody = new String();
postBody += "{";
for (String key : postRequestBody.keySet()) {
String result = String.format("\"%s\":\"%s\",", key, postRequestBody.get(key));
postBody += result;
}
System.out.println("body initialized");
postBody.substring(0, postBody.length() - 1);
postBody += "}";
try {
post.setEntity(new StringEntity(postBody));
} catch (UnsupportedEncodingException e) {
System.out.println(e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("entity set");
try {
if (post != null) {
System.out.println("starting request....");
HttpResponse response = sharedClient.execute(post);
System.out.println("responce recieved");
} else {
System.out.println("null request");
}
// System.out.println(response) ;
} catch (ClientProtocolException e) {
System.out.println(e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
System.out.println(e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
}
So, to start post-request, I simply do the following :
BL_SimpleAsyncTask obj = new BL_SimpleAsyncTask() ;
obj.requestServer = "https://api.orbios.com/v1/auth/sign-in" ;
obj.postRequestBody = new HashMap<String, String> () ;
obj.postRequestBody.put ("password", password) ;
obj.postRequestBody.put("email", email ) ;
obj.isPostRequest = true ;
System.out.println("start bg thread") ;
obj.doInBackground() ;
What am I doing wrong?
You are not supposed to call doInBackground() yourself. Just call execute() and let the framework call your doInBackground() in a background thread.
Instead of calling directly doInBackground() you should be calling execute method.
I want to load a data using JSON from php and then parsing it in android. I'm trying to implement asynctask in this process. And the return is in string. I got an error in
"Type mismatch : cannot convert from AsyncTask<String,String,String> to String in
ProsesTampil p = new ProsesTampil();
xResult = p.execute(urltampil);
The xResult is supposed to be the string value I got from php.
Here's the complete codes :
public void tampilkanData() {
try {
String nama = URLEncoder.encode(Login.usernameP, "utf-8");
urltampil += "?" + "&nama=" + nama;
txtNama.setText("");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ProsesTampil p = new ProsesTampil();
xResult = p.execute(urltampil);
try {
parse();
} catch (Exception e) {
e.printStackTrace();
}
}
private void parse() throws Exception {
//jObject = new JSONObject(xResult);
JSONArray menuitemArray = new JSONArray(xResult);
jObject=menuitemArray.getJSONObject(0);
String sret="";
txtBerat.setText(jObject.getString("berat_badan"));
txtNama.setText(jObject.getString("username"));
// txtUsia.setText(jObject.getString("usia"));
txtTinggi.setText(jObject.getString("tinggi_badan"));
//System.out.println(jObject.getString("jenis_kelamin").equalsIgnoreCase("female"));
if(jObject.getString("jenis_kelamin").equalsIgnoreCase("female")){
radioFemale.setSelected(true);
radioMale.setSelected(false);
}else{
radioMale.setSelected(true);
radioFemale.setSelected(false);
}
}
public String getRequestData(String UrlTampil){
String sret="";
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(UrlTampil);
try{
HttpResponse response = client.execute(request);
sret =request(response);
}catch(Exception ex){
Toast.makeText(this,"Gagal "+sret, Toast.LENGTH_SHORT).show();
}
System.out.println(sret);
return sret;
}
class ProsesTampil extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... params) {
return getRequestData(params[0]);
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
I'm sorry for my bad english. thanks in advance
The propose of an AsyncTask is execute some code in a separate thread (different from UI thread), but the result from that code, when ready, will be delivered in onPostExecute.i.e. The method execute returns the AynscTask itself,not String so change your code as
ProsesTampil p = new ProsesTampil();
xResult = p.execute(urltampil);
to
ProsesTampil p = new ProsesTampil();
p.execute(urltampil);
And get xResult in onPostExecute method as
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
xResult = result;
}
First Thing You can not return value from onPostExecute() because return type is void
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
Second Your class doesn't Return any value...
So if you want to get value of result try to get value from onPostExecute().
I mean to say do as follow..
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
xResult = result;
super.onPostExecute();
}
You can't do it because AsyncTask works in background thread.
Your result will come in UI thread after background has done self work:
#Override
protected void onPostExecute(String result) {
//String result - that what you need
}
execute() doesn't return a string. So you can't assign it like that. AsyncTasks are asynchronous- they don't finish until later. Any code you'd want to run on the result of an AsyncTask should be placed in the onPostExecute() function of the AsyncTask.
Yo can use
String results = yourAsyntask.get() instead of using yourAsyntask.execut()e method, it will return you result. same as Result get you in onPostExecute method;
But it will block your main thread.
I have an AsyncTask class which parse json data and inserts into an object, when I call it in normal activity classes it shows that data have been parsed but when I execute this on a class which extends Application then it gives zero result. Here is my class
public class AppGlobalData extends Application {
public ArrayList<YoutubeItem> gotItem= new ArrayList<YoutubeItem>();
private YouTubeParser parser;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
new ParserLoader().execute();
}
public class ParserLoader extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
Log.i("Succeed?", "Yes");
parser = new YouTubeParser(
"http://powergroupbd.com/youtube/getyoutubejson.php");
try {
gotItem = parser.parseInitiator();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
public ArrayList<YoutubeItem> getGotItem() {
return gotItem;
}
public void setGotItem(ArrayList<YoutubeItem> gotItem) {
this.gotItem = gotItem;
}
}
I cant figure out the problem, can anyone help?
please be noted that this class runs and logs my String but doesnt parse data.
I think what might happen is that when new ParserLoader().execute(); it doing the work asynchronously. When your Activity load and call the getGotItem() the Asynctask might not have finished
I'm new to android, please halp.
This is a really simple scenario, there's an actionbar, and when a tab is selected, I need to send an http request to get an article list, when the response arrives, update a listview and here's where I got this exception.
I'm aware that I should isolate network operations from UI thread, so I implement the network functions in an AsyncTask class.
The most weird part is, before I try to get the article list, I have actually called a network function once to log in, and that just works fine, no exceptions! And guess what, if I replace the get article list call with log in call, it works fine, too. All the code are just the same, except the arguments differ.
Here's how I do it, since too many modules will use the network module, I use a static wrapper:
UI -> Static Factory -> New AsyncTask -> Response arrives -> Call Static callback function in Static Factory -> Call callback function in UI
AsyncTask doInBackground
#Override
protected HttpResponse doInBackground(String... params) {
// TODO Auto-generated method stub
String uri = params[0];
HttpGet get = new HttpGet(uri);
try {
return _client.execute(get);
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
AsyncTask post execute
#Override
protected void onPostExecute(HttpResponse result) {
//Do something with result
if (result != null) {
try {
JSONObject json = FormJsonFromResponse();
Command.OnTaskComplete(json);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static wrapper code:
#Override
public static void OnTaskComplete(JSONObject json) {
// TODO Auto-generated method stub
if(_callback != null) {
_callback.OnCommandComplete(json);
}
}
Here's how I call asynctask in static wrapper:
public static void LogIn(String user, String pass) {
new NetworkTask().execute(_uriPrefix + login, _user, _pass);
}
Revise your AsyncTask following this pattern:
#Override
protected JSONObject doInBackground(String... params) {
// TODO Auto-generated method stub
String uri = params[0];
HttpGet get = new HttpGet(uri);
try {
HttpResponse response = _client.execute(get);
return FormJsonFromResponse();
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
AsyncTask post execute
#Override
protected void onPostExecute(JSONObject result) {
//Do something with result
if (result != null) {
try {
Command.OnTaskComplete( result );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This class causing me android.os.NetworkOnMainThreadException,i know that i have to use asyncTask to make it but i can't figure out how because i am using 1 fragments and this make my application very slow especially when i laod bitmaps, can any one help me please.
public class ContainerData {
static public Context context;
public ContainerData() {
}
public static ArrayList<Feed> getFeeds(String feedurl){
SAXParserFactory fabrique = SAXParserFactory.newInstance();
SAXParser parseur = null;
ArrayList<Feed> feeds = null;
try {
parseur = fabrique.newSAXParser();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
URL url = null;
try {
url = new URL(feedurl);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
DefaultHandler handler = new ParserXMLHandler();
try {
parseur.parse(url.openConnection().getInputStream(), handler);
feeds = ((ParserXMLHandler) handler).getData();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return feeds;
}
}
If you use AsyncTask make sure getFeeds is called inside the doInBackground(...) callback
Regardless of whether you use a fragment or not, you're still trying to perform Network activity on the main thread.
Create a generic class that extends AsyncTask which can perform all your parsing.
public class MyTaskHandler extends AsyncTask<String, Integer, Boolean>
{
#Override
protected void onPreExecute()
{
//Could display progress dialog here
}
#Override
protected Boolean doInBackground(String... params)
{
//Implement your parser here
}
#Override
protected void onPostExecute(Boolean result)
{
//Check result, dismiss dialog etc
}
}
Then create a new instance of MyTaskHandler and run it...
MyTaskHandler myTask = new MyTaskHandler();
myTask.execute("http://www.myxmlsite.com/lists.xml");
The execute method can take (String... params) so you can pass for example a URL,and retrieve it in doInBackground(String... params)
#Override
protected Boolean doInBackground(String... params)
{
//Implement your parser here
String urlToParse = params[0];
}
Best of luck.