How to pass a string in AsyncTask? - java

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);
}
}

Related

NetworkOnMainThreadException - Android/Java

I know there are some identical questions but I just couldn't figure out what I'm doing wrong.
public class MainActivity extends AppCompatActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
new JsonHandler().execute(this, collection, gridArray, customGridAdapter);
...
}
}
So in my main activity I need to query an API which gives back JSON and I have to process that to build my database.
Then in doInBackground() I call getAllCards() which gets the first JSON. Because the JSON includes URLs for more JSON requests, I have a few methods each querying a more detailed JSON.
public final class JsonHandler extends AsyncTask {
private final String urlCards = "https://api.gwentapi.com/v0/cards/";
private final String urlSpecificCard = "https://api.gwentapi.com/v0/cards/:id";
private Context context;
private Collection collection;
private ArrayList<Card> gridArray;
private CustomGridViewAdapter customGridAdapter;
public JsonHandler(Context context, Collection collection, ArrayList<Card> gridArray, CustomGridViewAdapter customGridAdapter){
this.context = context;
this.collection = collection;
this.gridArray = gridArray;
this.customGridAdapter = customGridAdapter;
}
public JsonHandler(){
this.context = null;
this.collection = null;
this.gridArray = null;
this.customGridAdapter = null;
}
private void getAllCards() throws RuntimeException {
JsonObjectRequest arrayRequest = new JsonObjectRequest(Request.Method.GET, urlCards, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
generateCollection(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError e) {
throw new RuntimeException(e.getMessage());
}
});
Volley.newRequestQueue(context).add(arrayRequest);
}
private void getSpecificCard(final String cardURL) throws RuntimeException {
JsonObjectRequest arrayRequest = new JsonObjectRequest(Request.Method.GET, cardURL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
processCard(response, collection);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError e) {
throw new RuntimeException(e.getMessage());
}
});
Volley.newRequestQueue(context).add(arrayRequest);
}
private void generateCollection(JSONObject response) throws RuntimeException {
try {
JSONArray array = response.getJSONArray("results");
for(int i = 0; i < array.length();i++){
JSONObject object = array.getJSONObject(i);
String cardURL = object.getString("href");
getSpecificCard(cardURL);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
private void processCard(JSONObject response, Collection collection){
try {
String id = response.getString("id");
EnumFaction faction = EnumFaction.valueOf(response.getJSONObject("faction").getString("name").toUpperCase());
EnumType type = null;
EnumRarity rarity = null;
EnumLane lane = null;
EnumLoyalty loyalty = null;
String name = response.getString("name");
String text = response.getString("text");
String imagePath = "https://api.gwentapi.com/media/\" + id + \"_small.png";
URL url = new URL(imagePath);
InputStream inputStream = url.openConnection().getInputStream();
Bitmap image = BitmapFactory.decodeStream(inputStream);
Card card = new Card(id, faction, type, rarity, lane, loyalty, name, text, null, imagePath, 0);
collection.addCard(card);
gridArray.add(card);
customGridAdapter.notifyDataSetChanged();
} catch (Exception e){
throw new RuntimeException(e.getMessage());
}
}
#Override
protected Object doInBackground(Object[] params) {
context = (Context) params[0];
collection = (Collection) params[1];
gridArray = (ArrayList<Card>) params[2];
customGridAdapter = (CustomGridViewAdapter) params[3];
getAllCards();
return null;
}
}
So now on to the problem:
When the programm reaches processCard() when I've gathered enough information, I get a NetworkOnMainThreadException when I create the InputStream.
I've tried so many different methods to get a Bitmap from my URL and different methods to do an asynchronous task - all leading to the same result.
If you could show me how to resolve this issue, I'd be sooo happy.
Edit: Since it got marked as duplicate: I AM USING ASYNCTASK! I have looked at many questions and tried what they did there, it doesn't work!
Not really familiar with how volley works but onResponse but be on the main thread so you need to start a new thread to make that call too

Returning object- OnPostExecute

I try to return array of objects with this function:
public static JSONEvent[] invokeFunction(String funName, String requestContent) {
final String functionName = funName;
final String requestPayload = requestContent;
new AsyncTask<Void, Void, InvokeResult>() {
#Override
protected InvokeResult doInBackground(Void... params) {
try {
final ByteBuffer payload =
ENCODER.encode(CharBuffer.wrap(requestPayload));
final InvokeRequest invokeRequest =
new InvokeRequest()
.withFunctionName(functionName)
.withInvocationType(InvocationType.RequestResponse)
.withPayload(payload);
final InvokeResult invokeResult =
AWSMobileClient
.defaultMobileClient()
.getCloudFunctionClient()
.invoke(invokeRequest);
return invokeResult;
} catch (final Exception e) {
Log.e("LAMBDA", "AWS Lambda invocation failed : " + e.getMessage(), e);
final InvokeResult result = new InvokeResult();
result.setStatusCode(500);
result.setFunctionError(e.getMessage());
return result;
}
}
#Override
protected void onPostExecute(final InvokeResult invokeResult) {
try {
final int statusCode = invokeResult.getStatusCode();
final String functionError = invokeResult.getFunctionError();
final String logResult = invokeResult.getLogResult();
if (statusCode != 200) {
//showError(invokeResult.getFunctionError());
} else {
final ByteBuffer resultPayloadBuffer = invokeResult.getPayload();
//resultPayloadBuffer.rewind();
// while (resultPayloadBuffer.hasRemaining())
// Log.e("BUFFER",resultPayloadBuffer.position() + " -> " + resultPayloadBuffer.get());
// User a = new User(23, 24);
//
// User b = new User(58, 59);
// User[] ab = new User[] {a, b};
// User [] events = new User[3];
ObjectMapper mapper = new ObjectMapper();
final String resultPayload = DECODER.decode(resultPayloadBuffer).toString();
Log.e("LAMBDA-SUCCESS", resultPayload);
try {
// String s2 = getJson2(ab);
// Log.e("S2", s2);
//User[] user2 = mapper.readValue(resultPayload, User[].class);
events = mapper.readValue(resultPayload, JSONEvent[].class);
// for (JSONEvent u : events)
// Log.e("USER",u.getLocationLat()+"");
Log.e("ARRAY",Arrays.toString(events));
} catch (Exception e) {
e.printStackTrace();
}
//return resultPayload;
// mResultField.setText(resultPayload);
}
if (functionError != null) {
Log.e("LAMBDA", "AWS Lambda Function Error: " + functionError);
}
if (logResult != null) {
Log.d("LAMBDA", "AWS Lambda Log Result: " + logResult);
}
}
catch (final Exception e) {
Log.e("LAMBDA", "Unable to decode results. " + e.getMessage(), e);
//showError(e.getMessage());
}
}
}.execute();
return events;
}
The problem is that I call invokeFunction in diffrent activity and it returns null but in onPostExecute the array is not null. It seems that it returns array before calling OnPostExecute. How to solve that?
The problem is that the method invokeFunction is finishing before onPostExecute (asynchronous)
You could use an interface to communicate AsyncTask and activity.
Interface (pseudocode):
public interface AsyncCom {
public void sendUsers(User [] events);
}
Your asynFunction (pseucode):
public void invokeFunction(String funName, String requestContent, AsyncCom listener) {
...
And call the function of the listener in postExecute (pseudocode):
protected void onPostExecute(final InvokeResult invokeResult) {
...
listener.sendUsers(events);
}
Declare the interface in your activity and call your method with the listener (pseudocode):
public class MyActivity implements AsyncCom {
...
invokeFunction(funName, requestContent, this);
...
Finally, in your activity, implements the returned method (pseudocode):
public void sendUsers(User [] events){
// do wathever you want with users
}
But remeber that the response will bw asynchonous
private void invokeFunction(String funName, String requestContent{
YourTask task = new YourTask();
task.execute(new String[]{funName, requestContent});
}
static class YourTask extends AsyncTask<String, Void, InvokeResult> {
#Override
protected InvokeResult doInBackground(String... params) {
String funName = params[0];
String requestContent = params[1];
// ...
}
#Override
protected void onPostExecute(final InvokeResult invokeResult) {
/// . ..
doWhatYouNeedWithTheResult(result);
}
};
}

Getting null object reference If i start 2nd activity before 3rd activity (No error if I move from 1st to 3rd directly)

I know its a common error , and i know lots of topics here were asking about the same error, but i tried alot of solutions and non works.
My application is like this:
1st activity is a sign in activity,
2nd is a menu to navigate where to go,
3rd is the customer's details.
I think i know where the problem is but i don't whats causing it
In the 2nd activity i am calling a function to get the customer id (the same function i am calling in the 3rd activity but without taking all the details i am only taking it's ID because i need it in other activities )
So result i am getting second time is always null , which is causing this error
so if i jump directly from 1st to 3rd app doesn't crash.
but (1st 2nd 3rd ) then the function will be called twice (even though i am storing data in a different object) and works only at the first time it's called
Hope i explained it well
now my code for 2nd activity:
public class AfterLogin extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new AsyncpkAbone().execute(SharedValues.AboneKod);
setContentView(R.layout.activity_after_login);
}
public void AboneBilgiPressed(View v){
Intent i = new Intent(AfterLogin.this, UserDetailsActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
}
protected class AsyncpkAbone extends AsyncTask<String,Void,UserDetailsTable>
{
#Override
protected UserDetailsTable doInBackground(String... params) {
// TODO Auto-generated method stub
UserDetailsTable userDetail2=null;
RestAPI api = new RestAPI();
try {
JSONObject jsonObj = api.GetUserDetails(params[0]);
JSONParser parser = new JSONParser();
userDetail2 = parser.parseUserDetails(jsonObj);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("AsyncUserDetails", e.getMessage());
}
return userDetail2;
}
#Override
protected void onPostExecute(UserDetailsTable result2) {
// TODO Auto-generated method stub
SharedValues.AboneKod =result2.getAboneKod();
SharedValues.pkAbone = result2.getPkAbone();
}
}
the Code for the 3rd activity (user details)
public class UserDetailsActivity extends AppCompatActivity {
TextView tvAdres, tvTelefon,tvpkAbone;
String Adres;
String WEBParola;
String Tel1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_details);
new AsyncUserDetails().execute(SharedValues.AboneKod);
tvAdres = (TextView) findViewById(R.id.tv_firstname);
tvAdres.setTextIsSelectable(true);
tvTelefon = (TextView) findViewById(R.id.tv_lastname);
tvTelefon.setTextIsSelectable(true);
tvpkAbone = (TextView) findViewById(R.id.tv_pkAbone);
tvpkAbone.setTextIsSelectable(true);
tvAdres.setText(Adres);
tvTelefon.setText(Tel1);
tvpkAbone.setText(String.valueOf( SharedValues.pkAbone));
}
protected class AsyncUserDetails extends AsyncTask<String,Void,UserDetailsTable>
{
#Override
protected UserDetailsTable doInBackground(String... params) {
// TODO Auto-generated method stub
UserDetailsTable userDetail=null;
RestAPI api = new RestAPI();
try {
JSONObject jsonObj = api.GetUserDetails(params[0]);
JSONParser parser = new JSONParser();
userDetail = parser.parseUserDetails(jsonObj);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("AsyncUserDetails", e.getMessage());
}
return userDetail;
}
#Override
protected void onPostExecute(UserDetailsTable result) {
// TODO Auto-generated method stub
tvAdres.setText(result.getAdres());
tvTelefon.setText(result.getTelefon());
}
}
the data i get from the function is stored in a object of type (userdetails tables)
the code for the Userdetailstable is (might be needed)
package com.artyazilim.art;
public class UserDetailsTable {
String Adres,Tel1,AboneKod,WEBParola;
int pkAbone;
public UserDetailsTable(String Adres, String Tel1, String AboneKod,
String WEBParola,int pkAbone) {
super();
this.Adres = Adres;
this.Tel1 = Tel1;
this.AboneKod = AboneKod;
this.WEBParola = WEBParola;
this.pkAbone = pkAbone;
}
public UserDetailsTable() {
super();
this.Adres = null;
this.Tel1 = null;
this.AboneKod = null;
this.WEBParola = null;
this.pkAbone = 0;
}
public String getAdres() {
return Adres;
}
public void setAdres(String adres) {
Adres = adres;
}
public String getTelefon() {
return Tel1;
}
public void setTelefon(String telefon) {
Tel1 = telefon;
}
public String getAboneKod() {
return AboneKod;
}
public void setAboneKod(String aboneKod) {
AboneKod = aboneKod;
}
public String getWEBParola() {
return WEBParola;
}
public void setWEBParola(String WEBParola) {
this.WEBParola = WEBParola;
}
public int getPkAbone() {
return pkAbone;
}
public void setPkAbone(int pkAbone) {
this.pkAbone = pkAbone;
}
}
the function which i am calling in the both Async is this:
public JSONObject GetUserDetails(String AboneKod) throws Exception {
JSONObject result = null;
JSONObject o = new JSONObject();
JSONObject p = new JSONObject();
o.put("interface","Service1");
o.put("method", "GetUserDetails");
p.put("AboneKod",mapObject(AboneKod));
o.put("parameters", p);
String s = o.toString();
String r = load(s);
result = new JSONObject(r);
return result;
}
and in the web service this is the GetUserDetails function:
public DataTable GetUserDetails(string AboneKod)
{
DataTable userDetailsTable = new DataTable();
userDetailsTable.Columns.Add(new DataColumn("Adres", typeof(String)));
userDetailsTable.Columns.Add(new DataColumn("Tel1", typeof(String)));
userDetailsTable.Columns.Add(new DataColumn("pkAbone", typeof(String)));
if (dbConnection.State.ToString() == "Closed")
{
dbConnection.Open();
}
string query = "SELECT Adres,Tel1,pkAbone FROM r_Abone WHERE AboneKod='" + AboneKod + "';";
SqlCommand command = new SqlCommand(query, dbConnection);
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
userDetailsTable.Rows.Add(reader["Adres"], reader["Tel1"], reader["pkAbone"]);
}
}
reader.Close();
dbConnection.Close();
return userDetailsTable;
}
the error i am getting when going from 2nd to 3rd is
java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.String com.artyazilim.art.UserDetailsTable.getAdres()' on a
null object reference
10-30 05:33:13.410 24881-24881/com.artyazilim.art E/AndroidRuntime:
at
com.artyazilim.art.UserDetailsActivity$AsyncUserDetails.onPostExecute(UserDetailsActivity.java:74)
10-30 05:33:13.410 24881-24881/com.artyazilim.art E/AndroidRuntime:
at
com.artyazilim.art.UserDetailsActivity$AsyncUserDetails.onPostExecute(UserDetailsActivity.java:47)
10
i know it seems like a duplicate and I know the rules search before ask,I have spent lots of time trying other's solutions but the reason i might didn't find the answer else where is because i don't know whats is actually causing this error so not knowing what to search for.
thanks in advance :)
In you second activity check if result2.getAboneKod(); is not returning a null object.
I think this is why when you open the 3rd activity from the 2nd, you have the NullPointerException.

Managing multiple Async tasks in android

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");
}
}

Android AsynchTask data return to Activity

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
}
});

Categories

Resources