I have an issue with AsyncTask
String latlong = "lat=48.8534100&lon=2.3488000";
city = "Paris";
getWeather w = new getWeather(latlong,this);
w.execute();
This gs.alerter() should be executed after the onpostexecute, but it's execued before
gs.alerter("thiss" + currentWeather); //This is a Log.i function
gs.cities.add(new City(city, currentWeather + "°", image));
initializeAdapter();
The AsyncTask class is :
public class getWeather extends AsyncTask<Void, Void, JSONObject> {
String latlong;
MainActivity obj;
JSONParser jParser = new JSONParser();
JSONObject json;
public getWeather(String latlong,MainActivity obj)
{
this.latlong = latlong;
this.obj = obj;
}
#Override
protected JSONObject doInBackground(Void... params) {
// TODO Auto-generated method stub
String URL = "http://api.openweathermap.org/data/2.5/weather?" +
latlong +
"&appid=APIKEY" +
"&units=metric";
json = jParser.getJSONFromUrl(URL);
return json;
}
#Override
protected void onPostExecute(JSONObject result) {
this.obj.setWeather(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
}
The setweather code is on the activity class :
public void setWeather(JSONObject obj){
try {
JSONObject main = obj.getJSONObject("main");
Double initWeather = new Double(main.getString("temp"));
int finalWeather = (int)Math.round(initWeather * 1) / 1;
this.currentWeather = Integer.toString(finalWeather);
This gs.alerter() should be executed just right after the .execute()
gs.alerter(this.currentWeather);
} catch (JSONException e) {
e.printStackTrace();
}
}
So the problem is that the code just after .execute() is executed after onpostexecute(). I want to execute it in this order :
.execute()
onpostexecute() to affect the currentWeather variable
And then add City ...
Any help is needed.
Thank you all
PS : I am a beginner in Android development :)
put this code into a method:
public void methodName() {
gs.alerter("thiss" + currentWeather); //This is a Log.i function
gs.cities.add(new City(city, currentWeather + "°", image));
initializeAdapter();
}
and now:
#Override
protected void onPostExecute(JSONObject result) {
this.obj.setWeather(result);
obj.methodName();
}
Create Interface
public interface OnTaskCompleted{
void onTaskCompleted();
}
Your Activity Code will look like
class YourActivity implements OnTaskCompleted {
void someFunctionToExecute()
{
String latlong = "lat=48.8534100&lon=2.3488000";
city = "Paris";
getWeather w = new getWeather(latlong,this);
w.execute();
}
// this code will be called after postExecute
void OnTaskCompleted(){
gs.alerter("thiss" + currentWeather);
gs.cities.add(new City(city, currentWeather + "°", image));
initializeAdapter();
}
}
Your AsyncTask Code Will look like
public class getWeather extends AsyncTask<Void, Void, JSONObject> {
String latlong;
MainActivity obj;
JSONParser jParser = new JSONParser();
JSONObject json;
public getWeather(String latlong,MainActivity obj)
{
this.latlong = latlong;
this.obj = obj;
}
#Override
protected JSONObject doInBackground(Void... params) {
// TODO Auto-generated method stub
String URL = "http://api.openweathermap.org/data/2.5/weather?" +
latlong +
"&appid=APIKEY" +
"&units=metric";
json = jParser.getJSONFromUrl(URL);
return json;
}
#Override
protected void onPostExecute(JSONObject result) {
this.obj.setWeather(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
obj.OnTaskCompleted(); // calling after postexecute
}
}
Related
there is any way that I can get the return data from execute action?
for example I have the next line that calls to the execute function - googlePlacesReadTask.execute(toPass); and the googlePlacesReadTask return some parser data to me. So how can I get this data that the action return to me ?
AsyncTask -
public class PlacesDisplayTask extends AsyncTask<Object, Integer, List<HashMap<String, String>>> {
JSONObject googlePlacesJson;
GoogleMap googleMap;
#Override
protected List<HashMap<String, String>> doInBackground(Object... inputObj) {
List<HashMap<String, String>> googlePlacesList = null;
Places placeJsonParser = new Places();
try {
googlePlacesJson = new JSONObject((String) inputObj[1]);
googlePlacesList = placeJsonParser.parse(googlePlacesJson);
} catch (Exception e) {
Log.d("Exception", e.toString());
}
if(String.valueOf(googlePlacesList) != "[]"){
//Find the place
}
else{
//No place found
}
return googlePlacesList;
}
}
second AsyncTask -
public class GooglePlacesReadTask extends AsyncTask<Object, Integer, String> {
String googlePlacesData = null;
GoogleMap googleMap;
#Override
protected String doInBackground(Object... inputObj) {
try {
googleMap = (GoogleMap) inputObj[0];
String googlePlacesUrl = (String) inputObj[1];
Http http = new Http();
googlePlacesData = http.read(googlePlacesUrl);
} catch (Exception e) {
Log.d("Google Place Read Task", e.toString());
}
return googlePlacesData;
}
#Override
protected void onPostExecute(String result) {
PlacesDisplayTask placesDisplayTask = new PlacesDisplayTask();
Object[] toPass = new Object[2];
toPass[0] = googleMap;
toPass[1] = result;
placesDisplayTask.execute(toPass);
}
}
Thanks.
Based on Which type of data you want to get from that method. If that method returns String data then save it in String variable.
For example :
In your case if googlePlacesReadTask returns String type of data then store it in string variable like :
String data = googlePlacesReadTask.execute(toPass);
Hope it will help
Use the onPostExecute method of your AsyncTask, there you have the response from the service (sent by the background process), handle it as you need.
If you need the data back in your class, you can send the AsyncTask a reference to it and call one class method from your AsyncTask sending it the required data
Just one way of doing it, there are more.
Dummy example:
public class MyAsyncTask extends AsyncTask<Void, Void, String> {
private MyClass myClass;
public MyAsyncTask(MyClass myClass) {
this.myClass = myClass;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
return something;
}
#Override
protected void onPostExecute(String something) {
super.onPostExecute(something);
if(myClass != null){
myClass.thereYouGo(something);
}
}
}
From your class (MyClass):
new MyAsyncTask(this).execute();
Receiver method in MyClass:
public void thereYouGo(String something){
// do what you want
}
I'm trying to fetch data from server in saving in SQLite database through Async task on Splash. i have multiple tables on server and need to fetch one after another. I'm trying this way
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork()
.penaltyLog().build());
url = getResources().getString(R.string.url);
db = new SQLCont(context);
new asyn_Task1(Splash.this).execute();
}
public class asyn_Task1 extends AsyncTask<String, Void, Boolean> {
public asyn_Task1(Splash activiy) {
context = activiy;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
new asyn_Task2(Splash.this).execute();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressdialog = new ProgressDialog(Splash.this);
progressdialog.setTitle("Processing....");
progressdialog.setMessage("Please Wait.....1 /10");
progressdialog.setCancelable(false);
progressdialog.show();
}
#Override
protected Boolean doInBackground(String... params) {
postParameters.add(new BasicNameValuePair("001", data));
try {
CustomHttpClient.executeHttpGet("001");
} catch (Exception e1) {
e1.printStackTrace();
}
String response = null;
// call executeHttpPost method passing necessary parameters
try {
response = CustomHttpClient.executeHttpPost(
url,
postParameters);
// store the result returned by PHP script that runs
// MySQL query
String result = response.toString();
// parse json data
try {
JSONArray jArray = new JSONArray(result);
for (int i = 0; i < jArray.length(); i++) {
JSONObject json_data = jArray.getJSONObject(i);
id = json_data.getString("id");
st_name = " " + json_data.getString("name");
st_contact = json_data.getString("contact");
st_category = json_data.getString("Category");
st_address = json_data.getString("address");
Log.d("favourite_data", "" + id + st_name + st_contact
+ st_category + st_address);
db.adddata_hospital(context, st_name,st_contact,
st_category, st_address);
}
} catch (JSONException e) {
Log.e("log_tag", "Error parsing data " + e.toString());
}
} catch (Exception e) {
Log.e("log_tag", "Error in http connection!!" + e.toString());
}
return null;
}
}
public class asyn_Task2 extends AsyncTask<String, Void, Boolean> {
public asyn_Task2(Splash activiy) {
context = activiy;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
new asyn_Task3(Splash.this).execute();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Boolean doInBackground(String... params) {
// some stuff here
}
return null;
}
}
public class asyn_Task3 extends AsyncTask<String, Void, Boolean> {
public asyn_blood_Group(Splash activiy) {
context = activiy;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
progressdialog.dismiss();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Boolean doInBackground(String... params) {
// some stuff here
}
return null;
}
}
problem is that data is added for asyn_Task1 it repeated every time
expected out put
abc def ghi
jkl mno pqr
mno pqr stu
But getting output
abc def ghi
abc def ghi
abc def ghi
You will get your data based on your query. If you always execute same query then you will always get same data.
And from my point of view if possible single AsyncTask for that purpose. when all the query is completed then onpostExecute() callback will fired.
I currently have multiple activity that needs to perform an asynctask for http post and I wish to make the asynctask as another class file so that the different activity can call the asynctask to perform the http post request and onPostExecute, call the method httpResult(result) in the activity that called the asynctask. I have tried to pass the activity in but I am unable to call the method in onPostExecute. How can I do that?
public class MyActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_MyActivity);
//logic here...
AsyncHttpPost asyncHttpPost = new AsyncHttpPost("someContent", this, dialog);
JSONObject data = new JSONObject();
data.put("key", "value");
try {
asyncHttpPost.execute(data);
}
catch (Exception ex){
ex.printStackTrace();
}
}
public static void httpResult(String result) {
//this method has to get called by asynctask to make changes to the UI
}
}
AsyncHttpPost.java
public class AsyncHttpPost extends AsyncTask<JSONObject, String, String> {
String recvdjson;
String mData="";
private ProgressDialog dialog;
private Activity activity;
public AsyncHttpPost(String data, Activity activity, ProgressDialog dialog) {
mData = data;
this.activity = activity;
this.dialog = dialog;
}
protected void onPreExecute()
{
dialog.show();
}
#Override
protected String doInBackground(JSONObject... params) {
//logic to do http request
return "someStringResult";
}
protected void onPostExecute(String result) {
dialog.dismiss();
activity.httpResult(result); //This line gives me error : The method httpResult(String) is undefined for the type Activity
}
}
Create an Interface called HttpResponseImpl in a seperate file and add the required method httpResult
interface HttpResponseImpl{
public void httpResult(String result);
}
Now implement this interface by you Activity class
public class MyActivity extends Activity implements HttpResponseImpl{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_MyActivity);
//logic here...
AsyncHttpPost asyncHttpPost = new AsyncHttpPost("someContent", this, dialog);
JSONObject data = new JSONObject();
data.put("key", "value");
try {
asyncHttpPost.execute(data);
}
catch (Exception ex){
ex.printStackTrace();
}
}
public void httpResult(String result){
//this method has to get called by asynctask to make changes to the UI
}
}
And your AsyncHttpPost class would be.
public class AsyncHttpPost extends AsyncTask<JSONObject, String, String> {
String recvdjson;
String mData="";
private ProgressDialog dialog;
private HttpResponseImpl httpResponseImpl;
public AsyncHttpPost(String data, HttpResponseImpl httpResponseImpl, ProgressDialog dialog) {
mData = data;
this.httpResponseImpl = httpResponseImpl;
this.dialog = dialog;
}
protected void onPreExecute()
{
dialog.show();
}
#Override
protected String doInBackground(JSONObject... params) {
//logic to do http request
return "someStringResult";
}
protected void onPostExecute(String result) {
dialog.dismiss();
httpResponseImpl.httpResult(result);
}
}
Implements this HttpResponseImpl interface with all you Activity class from which you want to do HttpRequest.
Generic AsyncTask Example
Call it like
new RetrieveFeedTask(new OnTaskFinished()
{
#Override
public void onFeedRetrieved(String feeds)
{
//do whatever you want to do with the feeds
}
}).execute("http://enterurlhere.com");
RetrieveFeedTask.class
class RetrieveFeedTask extends AsyncTask<String, Void, String>
{
String HTML_response= "";
OnTaskFinished onOurTaskFinished;
public RetrieveFeedTask(OnTaskFinished onTaskFinished)
{
onOurTaskFinished = onTaskFinished;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected String doInBackground(String... urls)
{
try
{
URL url = new URL(urls[0]); // enter your url here which to download
URLConnection conn = url.openConnection();
// open the stream and put it into BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
while ((inputLine = br.readLine()) != null)
{
// System.out.println(inputLine);
HTML_response += inputLine;
}
br.close();
System.out.println("Done");
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return HTML_response;
}
#Override
protected void onPostExecute(String feed)
{
onOurTaskFinished.onFeedRetrieved(feed);
}
}
OnTaskFinished.java
public interface OnTaskFinished
{
public void onFeedRetrieved(String feeds);
}
I created a class DataAdapter which launches threads to get data from webservices. When called in an activity using
DataAdapter.InitData();
how can I know when both threads are finished?
Thanks
Jul
public class DataAdapter {
private final static String URL = "http://www.mywebservice.com";
private final static String URL_AD = "http://www.mywebservice2.com";
public void InitData(){
new GetInitData().execute(URL);
new GetAd().execute(URL_AD);
}
private static class GetInitData extends AsyncTask<String, Integer, JSONObject> {
protected JSONObject doInBackground(String... urls) {
JSONObject json = RestJsonClient.getJSONObject(urls[0]);
return json;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(JSONObject json) {
//process data
}
}
private static class GetAd extends AsyncTask<String, Integer, JSONObject> {
protected JSONObject doInBackground(String... urls) {
JSONObject json = RestJsonClient.getJSONObject(urls[0]);
return json;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(JSONObject json) {
//process data
}
}
}
Use this:
public class DataAdapter {
private final String URL = "http://www.mywebservice.com";
private final String URL_AD = "http://www.mywebservice2.com";
private boolean finished = false;
public void InitData(){
new GetInitData(this).execute(URL);
new GetAd(this).execute(URL_AD);
}
public void finished(){
if(!finished){
finished = true;
}else{
Log.d("TAG","Both have finished"):
}
private class GetInitData extends AsyncTask<String, Integer, JSONObject> {
Activity ac = null;
public GetInitData(Activity ac){
this.ac=ac;
}
protected JSONObject doInBackground(String... urls) {
JSONObject json = RestJsonClient.getJSONObject(urls[0]);
return json;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(JSONObject json) {
//process data
ac.finished();
}
}
private class GetAd extends AsyncTask<String, Integer, JSONObject> {
Activity ac = null;
public GetInitData(Activity ac){
this.ac=ac;
}
protected JSONObject doInBackground(String... urls) {
JSONObject json = RestJsonClient.getJSONObject(urls[0]);
return json;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(JSONObject json) {
//process data
ac.finished();
}
}
}
Add a synchronized method to you DataAdapter class which each of the AsyncTask calles in its onPostExecute(). Within this method you set a boolean variable indicating that the first job finished, when the second AsyncTask calls the method it checks whether the first thread has already finished. If both have finished you can go one with your custom code.
I'm new to Android development and I'm trying to code a little app which allows me to grab an external JSON file and parse it. I got this to work, however it wont work if I try to execute it in the background as an AsyncTask. Eclipse gives me the error
The method findViewById(int) is undefined for the type LongOperation
in this line:
TextView txtView1 = (TextView)findViewById(R.id.TextView01);
Here is my code:
public class Main extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new LongOperation().execute();
}
}
class LongOperation extends AsyncTask<String, Void, String> {
private final Context LongOperation = null;
#Override
protected String doInBackground(String... params) {
try {
URL json = new URL("http://www.corps-marchia.de/jsontest.php");
URLConnection tc = json.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(tc.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
JSONArray ja = new JSONArray(line);
JSONObject jo = (JSONObject) ja.get(0);
TextView txtView1 = (TextView)findViewById(R.id.TextView01);
txtView1.setText(jo.getString("text") + " - " + jo.getString("secondtest"));
}
} catch (MalformedURLException e) {
Toast.makeText(this.LongOperation, "Malformed URL Exception: " + e, Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(this.LongOperation, "IO Exception: " + e, Toast.LENGTH_LONG).show();
} catch (JSONException e) {
Toast.makeText(this.LongOperation, "JSON Exception: " + e, Toast.LENGTH_LONG).show();
}
return null;
}
#Override
protected void onPostExecute(String result) {
}
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
ProgressDialog pd = new ProgressDialog(LongOperation);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Working...");
pd.setIndeterminate(true);
pd.setCancelable(false);
}
}
Any ideas on how to fix this?
Here is what you should do to make it work as you want. Use onPostExecude()
public class Main extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new LongOperation(this).execute();
}
}
class LongOperation extends AsyncTask<String, Void, String> {
private Main longOperationContext = null;
public LongOperation(Main context) {
longOperationContext = context;
Log.v("LongOper", "Konstuktor");
}
#Override
protected String doInBackground(String... params) {
Log.v("doInBackground", "inside");
StringBuilder sb = new StringBuilder();
try {
URL json = new URL("http://www.corps-marchia.de/jsontest.php");
URLConnection tc = json.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(tc.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
JSONArray ja = new JSONArray(line);
JSONObject jo = (JSONObject) ja.get(0);
Log.v("line = ", "jo.getString() ="+jo.getString("text"));
sb.append(jo.getString("text") + " - " + jo.getString("secondtest")).append("\n");
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.v("Error", "URL exc");
} catch (IOException e) {
e.printStackTrace();
Log.v("ERROR", "IOEXECPTOIn");
} catch (JSONException e) {
e.printStackTrace();
Log.v("Error", "JsonException");
}
String result = sb.toString();
return result;
}
#Override
protected void onPostExecute(String result) {
Log.v("onPostExe", "result = "+result);
TextView txtView1 = (TextView)longOperationContext.findViewById(R.id.textView01);
txtView1.setText(result);
}
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
ProgressDialog pd = new ProgressDialog(longOperationContext);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Working...");
pd.setIndeterminate(true);
pd.setCancelable(false);
}
}
The implementation of AsyncTask in one of the other answers is flawed. The progress dialog is being created every time within publishProgress, and the reference to the dialog is not visible outside the method. Here is my attempt:
public class Main extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new LongOperation().execute();
}
class LongOperation extends AsyncTask<String, Void, String> {
ProgressDialog pd = null;
TextView tv = null;
#Override
protected void onPreExecute(){
tv = Main.this.findViewById(R.id.textvewid);
pd = new ProgressDialog(Main.this);
pd.setMessage("Working...");
// setup rest of progress dialog
}
#Override
protected String doInBackground(String... params) {
//perform existing background task
return result;
}
#Override
protected void onPostExecute(String result){
pd.dismiss();
tv.setText(result);
}
}
}
You are trying to do something which won't work. First of all you are inside of a class that extends AsyncTask so you won't have that method available as it is a method of the class Activity.
The second problem is that you are trying to do UI stuff in a method that is not synchronized with the UI thread. That is nothing you would want to do.
Process your JSON response in the doInBackground method and pass the result to the onPostExecute method where you will be able to handle UI stuff as it is synchronized with the UI thread.
The current setup you have will not make it easier for you to handle what you are trying to do anyway. You could make your LongOperation class a private class of your Activity class and define the TextView as a instance member. Grab it off the layout using findViewById inside of your OnCreate and modify (set text or whatever) inside the onPostExecute method of your AsyncTask.
I hope it is somewhat clear what I meant.
findViewById is method in Activity class. You should pass instance of your activity to your LongOperation when you create it. Then use that instance to call findViewById.