I have a MainActivity class from which I am calling an instance of my JsonObj class.
JsonObj extends AsynchTask. It's pasted below:
public class JsonObj extends AsyncTask<String, Void, JSONObject>{
int tid;
String term;
#Override
protected JSONObject doInBackground(String... url) {
// TODO Auto-generated method stub
DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams());
HttpPost httppost = new HttpPost(url[0]);
JSONObject jsonObject = null;
// Depends on your web service
httppost.setHeader("Content-type", "application/json");
InputStream inputStream = null;
String result = null;
try {
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
inputStream = entity.getContent();
// json is UTF-8 by default
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null){
sb.append(line + "\n");
}
result = sb.toString();
// Log.e("JSON-Test [RESULT]: ", result);
jsonObject = new JSONObject(result);
} catch (Exception e) {
Log.e("JSON-Test [exception]: ", e.toString());
}
finally {
try{if(inputStream != null)inputStream.close();}catch(Exception squish){}
}
return jsonObject;
}
#Override
protected void onPostExecute(JSONObject result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
What I am trying to achieve is an AsyncTask class which I can call from any activity that will fetch and return JSON from my server.
My problem is my AsyncTask class successfully fetches my JSON but I am struggling to pass it back to my Activity.
I know the OnPostExecute function returns data on completion of my AsyncTask but all my attempts to access the data in my Activity class are not working.
I'm using new JsonObj().execute("http://myserver/json"); to call my JsonObj class.
How do I call OnpostExecute to directly access data my AsynchTask fetches from my server OR what is a better solution to this problem?
Create an Interface that has a method called something like "onServiceFinished" which your activities that make this call implement. Then when you call your AsyncTask, pass it (this) and in your onPostExectue, call FinishedListener.onServiceFinished(var1, var2) or whatever data your passing.
Code Example: This example uses an AsyncTask to retrieve a message from the server, and when that is finished, pass back that message to the class that requested it
Interface:
public interface ServiceHandler {
public abstract void onServiceFinished(JSONObject jsonObject);
}
Activity:
public class YourActivity extends Activity implements ServiceHandler {
#Override
public void onCreate(Bundle savedInstanceState) {
//Activity stuff
new JsonObj(this).execute("http://myserver/json");
}
#Override
public void onServiceFinished(JSONObject jsonObject) {
// Do something with the message
}
}
Asynctask:
public class JsonObj extends AsyncTask<String, Void, JSONObject> {
ServiceHandler handler;
public ChatAsync(ServiceHandler serviceHandler) {
handler = serviceHandler;
}
#Override
protected JSONObject doInBackground(String...params) {
// fetch messages from service and parse JSON
}
#Override
protected void onPostExecute(JSONObject json) {
handler.onServiceFinished(json);
}
}
The basic model is there, you'll have to modify it to fit what you're doing! Hope this helps
If you doing all network operation in a separate class and you want the result on the calling Activity class.
Create a method onTaskComplete(JsonObject result) on the calling Activity class.
public void onTaskComplete(JsonObject result) {
//Do You Operation
}
And now you need to call this method on OnPostExecute()
public class JsonObj extends AsyncTask<String, Void, JSONObject>{
Activity _context;
public JsonObj(Activity _context) {
this._context = _context;
}
#Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
this._context.onTaskComplete(result);
}
}
At last call the AsyncTask
new JsonObj(this).execute("YOUR URL");
The best way to do this is with a Callback. With this pattern, you create an interface that you implement in your Activity. You then set a method in this interface callback to be run in your onPostExecute() method. For example, this basic AsyncTask will call the callback function when complete:
public class JsonObj extends AsyncTask<Void, Void, JSONObject> {
private OnSuccessListener listener;
private String url;
public JsonObj(String url, OnSuccessListener listener) {
this.url = url;
this.listener = listener;
}
#Override
protected JSONObject doInBackground(Void... params) {
//handle url getter. returning the JSONObject here will send it to the onPostExecute method.
}
#Override
protected void onPostExecute(JSONObject json) {
if (listener != null)
listener.onSuccess(json);
}
public interface OnSuccessListener {
public void onSuccess(JSONObject json);
}
}
Then to use this properly, just do this in your Activity:
new JsonObj("http://myserver/json", new OnSuccessListener() {
#Override
public void onSuccess(JSONObject json) {
//TODO: handle new JSONObject.
}
}).execute();
If you want a simpler, already coded solution, consider the droidQuery library that I wrote. Apart from simplifying animations and common UI tasks, it can simplify this sort of network call immensely. The above code can be compressed down to this in your Activity:
$.ajax(new AjaxOptions().url("http://myserver/json")
.type("POST")
.dataType("JSON")
.headers(new Headers().content_type("application/json"))
.success(new Function() {
#Override
public void invoke($ d, Object... args) {
JSONObject json = (JSONObject) args[0];
//TODO: handle json
}
});
Related
I'm connecting to API with the async task. I need to pass two values from the API to the app, in onResponse I have logged the values and got them right. But in onPostExecute one of them keep turning into null
I have already tried to check different values from API and logs to see if the value that I'm looking for is there or if the connection is valid, everything went alright until it hits the onPostExecute where I'm getting only one value
public class ChooseLocationTask extends AsyncTask<String, Void, Void> {
OkHttpClient client = new OkHttpClient.Builder()
//default timeout for not annotated requests
.readTimeout(15000, TimeUnit.MILLISECONDS)
.connectTimeout(15000, TimeUnit.MILLISECONDS)
.writeTimeout(15000, TimeUnit.MILLISECONDS)
.build();
Request request;
private TextView location;
private TextView value;
String state;
Number probability;
String probablityString;
public ChooseLocationTask(TextView location, int selected, TextView value){
this.location = location;
this.value = value;
}
#Override
protected void onProgressUpdate(Void...values){
super.onProgressUpdate(values);
}
#Override
protected void onPreExecute(){
super.onPreExecute();
}
#Override
protected Void doInBackground(String... urls) {
request = new Request.Builder().url(urls[0]).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
Log.d("CallMsg", String.valueOf(call));
}
#Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("Response", String.valueOf(response));
try {
JSONObject jsonObject = new JSONObject(response.body().string());
JSONObject weather = jsonObject.getJSONObject("weather");
JSONObject location = weather.getJSONObject("location");
state = location.getString("state");
JSONObject percentage = jsonObject.getJSONObject("probability");
JSONObject calculated = percentage.getJSONObject("highest");
probability = calculated.getInt("value");
probablityString = probability.toString();
Log.d("percentage", probability.toString());
Log.d("String",probablityString);
Log.d("location",state);
} catch (JSONException e){
e.printStackTrace();
}
}
});
return null;
}
#Override
protected void onPostExecute(Void voids){
if(isCancelled()){
voids= null;
} else {
location.setText(state);
value.setText("your chance to see Northern lights today is" + probablityString);
Log.d("value", "onPostExecute: " + probablityString);
}
Log.d("post", "onPostExecute: " + probability);
}
}
Basically, all I need is advice on how to get this value, I feel like maybe I made mistake when converting it into a string, but in logs, in onResponse it shows quite alright, so I don't know. Thank you for all the advice
Retrofit has two techniques for performing requests, one synchronous (execute()) and another asynchronous (enqueue()). You are using the asynchronous technique, and as a result, when you go to execute your AsyncTask, your doInBackground() method immediately calls enqueue(), completes, and calls onPostExecute() before your request has completed.
You have two options. First, you can keep your current AsyncTask, but replace enqueue() for execute(). This will look a little like:
public class ChooseLocationTask extends AsyncTask<String, Void, Void> {
private final OkHttpClient client = new OkHttpClient.Builder()
//default timeout for not annotated requests
.readTimeout(15000, TimeUnit.MILLISECONDS)
.connectTimeout(15000, TimeUnit.MILLISECONDS)
.writeTimeout(15000, TimeUnit.MILLISECONDS)
.build();
private final Request request;
private final TextView location;
private final TextView value;
String state;
Number probability;
String probablityString;
public ChooseLocationTask(TextView location, int selected, TextView value){
this.location = location;
this.value = value;
}
#Override
protected Void doInBackground(String... urls) {
request = new Request.Builder().url(urls[0]).build();
try {
final Response<?> response = client.newCall(request).execute();
if(response.isSuccessful()) {
final JSONObject jsonObject = new JsonObject(response.body().string());
//etc...
}
} catch (IOException e) {
//...
}
//I'd recommend you return values as well, rather than assigning them to
//instance variables
return null;
}
#Override
protected void onPostExecute(Void voids){
if(isCancelled()){
voids= null;
} else {
location.setText(state);
value.setText("your chance to see Northern lights today is" + probablityString);
Log.d("value", "onPostExecute: " + probablityString);
}
Log.d("post", "onPostExecute: " + probability);
}
Or, you can get rid of your AsyncTask entirely, and just call enqueue()
So I have a URL within Method1 like so
public void Method1 (String x) {
String Url = "http://MYURL.com/?country=" + x + "&api_key=APIKEY";
new AsyncTaskParseJson().execute();
}
I need to pass the Url into my AsyncTask which is as follows
public class AsyncTaskParseJson extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {}
#Override
protected String doInBackground(String... arg0) {
try {
// create new instance of the httpConnect class
httpConnect jParser = new httpConnect();
// get json string from service url
String json = jParser.getJSONFromUrl(ServiceUrl);
// save returned json to your test string
jsonTest = json.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String strFromDoInBg) {
textLastLocation = (TextView) findViewById(R.id.lastlocation);
textLastLocation.setText(jsonTest);
}
}
I need it so the ServiceUrl = the Url from the method. I can't figure out how to do this even from looking at other peoples questions and answers
The first parameter on AsyncTask<First, Second, Third> will define the parameter to be passed on execute(), so you define it as String and pass the url. Then:
public void Method1 (String x) {
String Url = "http://MYURL.com/?country=" + x + "&api_key=APIKEY";
new AsyncTaskParseJson().execute(url);
}
On your AsyncTask, you can get it on the arg0 (array), i(ndex based on the order on how you passed it on execute())
public class AsyncTaskParseJson extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {}
#Override
protected String doInBackground(String... arg0) {
String url = arg0[0]; // this is your passed url
try {
// create new instance of the httpConnect class
httpConnect jParser = new httpConnect();
// get json string from service url
String json = jParser.getJSONFromUrl(ServiceUrl);
// save returned json to your test string
jsonTest = json.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String strFromDoInBg) {
textLastLocation = (TextView) findViewById(R.id.lastlocation);
textLastLocation.setText(jsonTest);
}
}
Hey everyone so I am just starting a part two for online training app and trying to adapt my async task to get movie reviews from the movie db. Having a totally different async task just for that seems like there should be a better way. Here is the current async task implementation that only gets the movie data.
The question is how do I add another async task to this in order to retrive the movie reviews as well from this url /movie/{id}/videos.
public FetchMovieData(Context context, GridView grid, boolean sortType, ITaskCompleteListener listener) {
mContext = context;
this.mMoviesGrid = grid;
this.mSortByMostPopular = sortType;
this.mTaskCompleteListener = listener;
}
#Override
protected Void doInBackground(String... 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;
try {
URL url;
if(mSortByMostPopular)
url = new URL(mContext.getString(R.string.picasso_url_popular_movies));
else
url = new URL(mContext.getString(R.string.picasso_url_highest_rated));
// Create the request to OpenWeatherMap, 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.
mMovieJsonStr = 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.
mMovieJsonStr = null;
}
mMovieJsonStr = buffer.toString();
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attempting
// to parse it.
mMovieJsonStr = null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mMovieJsonStr != null)
Constants.mMovies = MovieDataParser.getMovieData(mMovieJsonStr);
mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
}
So some one had suggested using Retrofit instead of having multiple async tasks. This seems like a good idea but I am having a lot of trouble understanding how it is supposed to work. Currently I have a WebService class an interface and am trying to use it to retrieve both movies and am going to add reviews then trailers. The issue is if I set the base url as "http://api.themoviedb.org" I get url must start with "/" in logcat.
Current code:
public class WebService {
public List<Movie> getMovies() {
RestAdapter retrofit = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org")
.build();
MovieDBService service = retrofit.create(MovieDBService.class);
return service.listMovies("movies");
}
}
public interface MovieDBService {
#GET("/3/discover/{switchterm}sort_by=popularity.desc&api_key=d273a1a1fb9390dab9 7ac0032b12366a")
List listMovies(#Path("switchterm") String switchterm);
}
//In code getting movies
WebService service = new WebService();
List movies = service.getMovies();
I think you have a lots of possibilities for doing this.You can follow this approach: add a second call to another AsyncTask when the first is finish, and pass to it a list of strings with the video ids:
public class FetchMovieData extends AsyncTask<Void, Void, Void> {
protected Boolean doInBackground() {
try {
String movieJSONString = getJSONMovies();
String[] ids = parseIdsFromJSON(movieJSONString);
if(ids.lenth != 0) {
FetchMovieReviews moviesReviewsAsyncTask = new FetchMovieReviews();
moviesReviewsAsyncTask.execute(ids);
} else {
return false;
}
return true;
} catch (Exception e) {
return false;
}
}
protected String getJSONMovies() {
//with the code you post, return the json string
}
protected String[] parseIdsFromJSON(String JSON) {
//parse the json and get the ids and return
//return {"1","2","3"}
}
}
public class FetchMovieReviews extends AsyncTask<String[], Void, Void> {
protected Void doInBackground(String[]... params) {
for(String id : params[0]) {
//call the web service and pass the id
}
return null;
}
}
You can put all the functionality for manage the calls to the web services in a MoviesRESTCalls class, and for manage the json in a MoviesJSONParser class or something like that, and the code is going to be much more clear.
So what I ended up with was this using the the Retrofit library for the web service. Thanks for the help everyone and let me know your thoughts.
public Context mContext;
private MovieJSON mMovieData;
private ReviewJSON mMovieReviews;
private VideoJSON mMovieVideos;
public boolean mSortByMostPopular;
ITaskCompleteListener mTaskCompleteListener;
public FetchMovieData(Context context, boolean sortType, ITaskCompleteListener listener) {
mContext = context;
this.mSortByMostPopular = sortType;
this.mTaskCompleteListener = listener;
}
public void getMovies() {
new FetchMovies().execute();
}
public void getReviews() {
new FetchReviews().execute();
}
public void getVideos() {
new FetchTrailers().execute();
}
private class FetchMovies extends AsyncTask<String, Void, Void > {
#Override
protected Void doInBackground(String... params) {
WebService service = new WebService();
//TODO Re-Implement sorting
mMovieData = service.getMovies();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mMovieData != null)
Constants.mMovies = MovieDataParser.getMovieData(mMovieData);
mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
}
}
private class FetchReviews extends AsyncTask<String, Void, Void > {
#Override
protected Void doInBackground(String... params) {
WebService service = new WebService();
mMovieReviews = service.getReviews();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mMovieReviews != null)
Constants.mReviews = MovieDataParser.getReviewData(mMovieReviews);
mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
}
}
private class FetchTrailers extends AsyncTask<String, Void, Void > {
#Override
protected Void doInBackground(String... params) {
WebService service = new WebService();
mMovieVideos = service.getVideos();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mMovieVideos != null)
Constants.mTrailers = MovieDataParser.getVideoData(mMovieVideos);
mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
}
}
//web service
public class WebService {
RestAdapter mRetrofit;
MovieDBService mService;
public WebService() {
mRetrofit = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org")
.build();
mService = mRetrofit.create(MovieDBService.class);
}
public MovieJSON getMovies() {
return mService.listMovies("");
}
public ReviewJSON getReviews() {
return mService.listReviews("76341");
}
public VideoJSON getVideos() {
return mService.listVideos("76341");
}
}
I am Calling a Asynctask from Mainactivity Using alarm manager Every 5 minutes
My Asynctask is kept in a New Service Class.
Using that Asynctask I'm retrieving String values from Web service.
Retrieving from web Service Saving in String Array Works fine.
Problem:
I want pass that String Array value from Web service doInBackground to Mainactivity is Getting Null.
Help me how to achieve this.
link i refered ,but no success
private class AsyncCallWSfor_SERVICE extends AsyncTask<String, Void, Void>
{
#Override
protected Void doInBackground(String... params)
{
Log.i(TAG1, "doInBackground");
try
{
getdatafromWeb();
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(),
"error caught in do in background", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute()
{
/* //progress.setTitle("Progress");
progress.setMessage("Please Wait Loading Data...");
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.setIndeterminate(true);
progress.show();*/
Log.i(TAG1, "onPreExecute");
}
#Override
protected void onPostExecute(Void result)
{
// To dismiss the dialog
// progress.dismiss();
Log.i(TAG1, "onPostExecute");
}
}
public void getdatafromWeb() {
// Create request
SoapObject request = new SoapObject(NAMESPACE1, METHOD_NAME1);
// Create envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
// Set output SOAP object
envelope.setOutputSoapObject(request);
// Create HTTP call object
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL1);
try {
// Invole web service
androidHttpTransport.call(SOAP_ACTION1, envelope);
// Get the response
SoapPrimitive response1 = (SoapPrimitive) envelope.getResponse();
//Converting string to Array list
ArrayList<String> KitDistributedString_array= new ArrayList<String>();
if ((response1.toString()).contains("{")) {
SoapObject rep = (SoapObject) envelope.bodyIn;
JSONArray jr = new JSONArray(rep.getPropertyAsString(0)
.toString());
for (int i = 0; i < jr.length(); i++) {
JSONObject jb = (JSONObject) jr.get(i);
KitValueString = jb.getString("KitValue");
Log.d(TAG1 +"MY Data" , KitValueString);
KitDistributedString_array.add(KitValueString);
}
STRING_ARRAY = new String[KitDistributedString_array.size()];
STRING_ARRAY = KitDistributedString_array.toArray(STRING_ARRAY);
}
else
{
Status_Response_Service = response1.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
}
I want to pass this STRING_ARRAY to MainActivity
For getting the response to the caller activity, I suggest to write a interface Which you need to implement to caller activity
e.g
public interface WebCallable {
public void response(String[] result);
}
implement interface to activity as below
public class MainActivity extends Activity implements WebCallable
Now extend service class from AsyncTask<String, Void, String[]> and pass activity object as paramenter by 'this'. You can save this object at class level.
e.g.
public AsyncCallWSfor_SERVICE(Context context){
this.context = context
}
In onPostExecute write
context.response(STRING_ARRAY)
Better, return string response from doInBackground and get it in onPostExecute as bekow
protected void onPostExecute(String result)
and create array in onPostExecute.
Or cretae STRING_ARRAY object class level.
I'm just learning about AsyncTask and want to use it as a separate class, rather then a subclass.
For example,
class inetloader extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(urls[0]);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
#Override
protected void onPostExecute(String result) {
Log.e("xx",result);
// how do I pass this result back to the thread, that created me?
}
}
and the main(ui) thread:
inetloader il = new inetloader();
il.execute("http://www.google.com");
//il.onResult()
//{
///do something...
//}
Thanks!
Use a interface. Something like:
interface CallBackListener{
public void callback();
}
Then do this in your UI thread:
inetloader il = new inetloader();
li.setListener(this);
il.execute("http://www.google.com");
In inetloader, add:
CallBackListener mListener;
public void setListener(CallBackListener listener){
mListener = listener;
}
then In postExecute(), do:
mListener.callback();
you can pass the activity instance to constructor and call activity function from there...
Like use interface :
public interface ResultUpdatable {
public void setResult(Object obj);
}
Implement this in the Activity and pass in the constructor of Async task and update the result from onPostExecute using setResult function.
inetloader il = new inetloader();
il.execute("http://www.google.com");
String result = il.get();//put it in try-catch
^^^^^^^^
here you get result which is in onPostExecute(String result)