Execute Async Task Inside another Async Task - java

I am trying to call another async task inside an OnPostExecute. The 2nd task does not run at all it seems. I am unable to print anything from within to the logs.
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
JSONObject json = new JSONObject(result);
JSONArray lignes = json.getJSONArray("lignes");
populatelist(lignes);
}
catch (JSONException e) {
}
}
}
The populatelist function fills an array. Inside this function, I try to call the 2nd async task to get values based on this list.
protected void populatelist(JSONArray lignes){
try {
for(int i=0;i<lignes.length(); i++) {
JSONObject jsonas = lignes.getJSONObject(i);
String fdesignation = jsonas.getString("designation");
String fqtecde = jsonas.getString("qtecde");
String fcode_produit = jsonas.getString("code");
InfoStock(fcode_produit);
items.add(new PickingListProduitItem(fdesignation,"",fqtecde, ""));
}
}
catch(Exception e){
}
}
InfoStock() is the function that is used to return additional from a web service.
protected void InfoStock(String code_produit){
String stockURL = "http://" + mSharedPreferences.getString(Constants.SERVER_IP,"")+"//rest/v2/produit/info/code/"+ code_produit + "?stock=true";
try {
if (mDownloader != null && mDownloader.getStatus() == AsyncTask.Status.RUNNING) {
mDownloader.cancel(true);
mPDialog.dismiss();
}
mPDialog = new ProgressDialog(getApplicationContext());
mDownloader = new XMLDownloader(getApplicationContext(),mPDialog);
byte[][] downloadResults = mDownloader.execute(stockURL).get();
// Read stock info.
String s = new String(downloadResults[0], StandardCharsets.UTF_8);
JSONObject resp = new JSONObject(s);
PrixStockJSONParser psj = new PrixStockJSONParser(resp);
mRepInfoStock = psj.getRepInfoStock();
mRepInfoPrix = psj.getRepInfoPrix();
} catch (Exception ex) {
}
}
I am trying to set a value in the array <> created in the OnPostExecute Method. However there is no error message and the array is not populated at all. Even if I try to print a log from the InfoStock function, it does nothing.
Any suggestions are welcome.

Related

Unable to access current value of Global Variable in Java

Below is my code, lat_val and long_val is not getting updated with received value from JSON response in btnShowLoc(), it is referencing to the default value which is 0,0. I want the global variable to keep updating when ever referenced and updated with JSON response.
public class MainActivity extends Activity {
public static String lat_val = "0";
public static String long_val = "0";
public String readJSONFeed(String urlStr) {
StringBuilder stringBuilder = new StringBuilder();
try {
URL url = new URL(urlStr);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("SisApiKey", "4572c3c9-73cb-4958-9649-26c1e8df27e8");
urlConnection.setRequestProperty("SisSmartKey", "d1aebd25-774c-4e8a-b3a5-ee5a603cc603");
InputStream ins = urlConnection.getInputStream();
urlConnection.connect();
int statusCode = urlConnection.getResponseCode();
if (statusCode == 200) {
BufferedReader br = new BufferedReader(new InputStreamReader(ins));
String line;
while ((line = br.readLine()) != null) {
stringBuilder.append(line);
}
ins.close();
} else {
Log.d("JSON", "Failed to download file");
}
} catch (java.net.MalformedURLException e) {
e.printStackTrace();
} catch (java.io.IOException e) {
e.printStackTrace();
} catch (Exception e) {
Log.d("readJSONFeed", e.getLocalizedMessage());
}
return stringBuilder.toString();
}
public class ReadJSONFeedTask extends AsyncTask
<String, Void, String> {
protected String doInBackground(String... url) {
return readJSONFeed(url[0]);
}
protected void onPostExecute(String result) {
try {
JSONObject jsonObject = new JSONObject(result);
//JSONObject flags = new JSONObject(jsonObject.getString("flag"));
JSONObject locationItems = new JSONObject(jsonObject.getString("response"));
//Log.v("Location Details :", locationItems.toString());
String []dev_loc = locationItems.toString().split("[\\s*,\\s*]");
MainActivity.lat_val = dev_loc[0]; //"12.9934136";
MainActivity.long_val = dev_loc[1]; //"80.2464206";
} catch (Exception e) {
Log.d("ReadJSONFeedTask", e.getLocalizedMessage());
}
}
}
public void btnGetDevLoc(View view) {
String sp_val = String.valueOf(spinner1.getSelectedItem());
new ReadJSONFeedTask().execute(
"http://15.153.133.160:21743/sis/sie/api/v1/applications/bb9f05fb-a796-4b75-9db7-c999360ad185/virtualobjects/d77d3905-aa77-41b9-9034-b0052bfde405?secondString=HWE_ASSET_ANDROID"); // + sp_val);
}
public void btnShowLoc(View view) {
//lat_val = "12.9934136";
//long_val = "80.2464206";
Intent in = new Intent(MainActivity.this, MapActivity.class);
Bundle bundle = new Bundle();
bundle.putString("latitude", MainActivity.lat_val);
bundle.putString("longitude", MainActivity.long_val);
in.putExtras(bundle);
startActivity(in);
}
With the few information you have shared, and given that
btnGetDevLoc() and btnShowLoc()are the functions executed when clicked on buttons in the application defined in activity_main.xml
and that
First btnGetDevLoc() is called then btnShowLoc()
the first thing that pops out in my mind is that the AsyncTask has not yet finished updating the String values, when you call btnShowLoc().
So, if btnGetDevLoc() and btnShowLoc() are called sequentially, like
... onClick() {
btnGetDevLoc();
btnShowLoc();
}
then it's most likely due to what I said above. Remember that AsyncTask runs asynchronously (as the name says...).
You can test this really small program.
public static double var1 = 0.0;
public static void main(String[] args) {
new Thread(() -> {
var1 = 1.0;
}).start();
System.out.println(var1);
}
It will almost always print 0.0, because the value of var1 is not updated yet when the main thread prints it.
What you should do is place your btnShowLoc() call at the end of onPostExecute(String). This guarantees that your method is called only after you have updated the new values.
I can't Understand, when the btnGetDevLoc() and btnShowLoc() called? Can you post your whole MainActivity?
Edit :
It's seems like you call btnShowLoc() before your AsyncTask finish its proccess.
You can change your code this way to make sure your btnShowLoc() called after your AsyncTask :
public class ReadJSONFeedTask extends AsyncTask
<String, Void, String> {
protected String doInBackground(String... url) {
return readJSONFeed(url[0]);
}
protected void onPostExecute(String result) {
try {
JSONObject jsonObject = new JSONObject(result);
//JSONObject flags = new JSONObject(jsonObject.getString("flag"));
JSONObject locationItems = new JSONObject(jsonObject.getString("response"));
//Log.v("Location Details :", locationItems.toString());
String []dev_loc = locationItems.toString().split("[\\s*,\\s*]");
MainActivity.lat_val = dev_loc[0]; //"12.9934136";
MainActivity.long_val = dev_loc[1]; //"80.2464206";
btnShowLoc(dev_loc[0], dev_loc[1]);
} catch (Exception e) {
Log.d("ReadJSONFeedTask", e.getLocalizedMessage());
}
}
}
public void btnShowLoc(String latitude, String longitude) {
//lat_val = "12.9934136";
//long_val = "80.2464206";
Intent in = new Intent(MainActivity.this, MapActivity.class);
Bundle bundle = new Bundle();
bundle.putString("latitude", latitude);
bundle.putString("longitude", longitude);
in.putExtras(bundle);
startActivity(in);
}

How to pass two different JSON Objects to processFinish at two different times

I have this MainActivity which does two HTTP calls and return the JSON object back to the MainActivity class. I have seperately implemented the AsyncTask class and used the AsyncResponse interface to get the JSON object to the MainActivity by using the processFinish function call.
At first I came up with one HTTP call which worked perfectly.
Secondly I wanted to do another HTTP call in the same activity class. So I edit the code to cater the second HTTP call.
When I run the application, only the first HTTP call is working. When I call the second HTTP call it throws an exception saying reference to a null object
Then I checked by logging the onPostExecute method which calls the processFinish function. There I could see the JSON Object. So, that means the second JSON object doesn't get to the processFinish
How do I manage the second HTTP call? Please help me! I am new to Android.
Following is my AsyncTask class...
public class ServiceHandler extends AsyncTask<String, Void, JSONObject> {
String startStationID;
String endStationID;
String searchDate;
String startTime;
String endTime;
public ServiceHandler(String startStationID, String endStationID, String searchDate, String startTime, String endTime) {
this.startStationID = startStationID;
this.endStationID = endStationID;
this.searchDate = searchDate;
this.startTime = startTime;
this.endTime = endTime;
}
public interface AsyncResponse {
void processFinish(JSONObject output);
}
public AsyncResponse delegate=null;
public ServiceHandler(AsyncResponse delegate) {
this.delegate = delegate;
}
#Override
protected JSONObject doInBackground(String... params) {
String method = params[0];
JSONObject JSON_Object = null;
if (method.equals("getStations")) {
JSON_Object = Constants.apiCall("http://api.lankagate.gov.lk:8280/railway/1.0/station/getAll?lang=en");
} else if (method.equals("searchTrains")) {
JSON_Object = Constants.apiCall("http://api.lankagate.gov.lk:8280/railway/1.0/train/searchTrain?" +
"startStationID="+this.startStationID+"&" +
"endStationID="+this.endStationID+"&" +
"searchDate="+this.searchDate+"&" +
"startTime="+this.startTime+"&" +
"endTime="+this.endTime+"&" +
"lang=en");
}
return JSON_Object;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(JSONObject obj) {
try{
Log.d("onPostExecute",obj.toString());
delegate.processFinish(obj);
}catch (Exception e){
Log.e("onPostExecute",e.getMessage());
}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
}
Following is my processFinish function...
#Override
public void processFinish(JSONObject output) {
Log.d("processFinish",output.toString());
if(!isSearchClicked) {
//Get all the stations...
if (output != null) {
Toast.makeText(MainActivity.this, "Successfully Connected!", Toast.LENGTH_SHORT).show();
try {
JSONObject obj = output.getJSONObject("RESULTS");
output = null;
JSONArray dataArray = obj.getJSONArray("stationList");
for (int i = 0; i < dataArray.length(); i++) {
JSONObject object1 = dataArray.getJSONObject(i);
String stationID = object1.getString("stationID");
String stationName = object1.getString("stationName");
stationNames.add(stationName);
stationIDs.add(stationID);
// stations.put(stationID,stationName);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Toast.makeText(MainActivity.this, " Connection Failed!", Toast.LENGTH_SHORT).show();
}
}else {
//search click action...
if (output != null) {
Toast.makeText(MainActivity.this, "Successfully Searched!", Toast.LENGTH_SHORT).show();
try {
JSONObject obj = output.getJSONObject("RESULTS");
JSONArray directTrains = obj.getJSONArray("directTrains");
// Log.d("array size",String.valueOf(directTrains.length()));
// for (int i = 0; i < directTrains.length(); i++) {
// JSONObject object1 = directTrains.getJSONObject(i);
//
// String stationID = object1.getString("stationID");
// String stationName = object1.getString("stationName");
// Log.d("JArr", stationID + " : " + stationName);
//
// stationNames.add(stationName);
// stationIDs.add(stationID);
//// stations.put(stationID,stationName);
// }
// Log.d("stationNames", stationNames.toString());
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Toast.makeText(MainActivity.this, " Connection Failed!", Toast.LENGTH_SHORT).show();
Log.d("output",output.toString());
}
}
}
Following is my first HTTP call...
ServiceHandler sh = new ServiceHandler(this);
String method = "getStations";
sh.execute(method);
Following is my second HTTP call...
String method = "searchTrains"
ServiceHandler sh = new ServiceHandler(startStationID,endStationID,searchDate,startTime,endTime);
sh.execute(method);
Although I don't understand exactly what your problem is. There are few things I suggest you to do.
Here I go.
Don't use AsyncTask to make your http calls , use an intent services instead.
Use a OkHTTP library for your networking source
On your intent service send local broadcast with LocalBroadcastManager to broadcast your results from the http call.
Register broadcastsReceivers within your activities or fragments that will listen for those broadcasts that comes from the intent service
Why not to use AsyncTask: Because of configuration change - if you rotate your device you will lose that network calls-
Read about intent services here

Weird issue while parsing JSONObjects and converting to Java objects

This is the first time I am facing a very weird problem. I have a JSONObject mentioned below.:
Link for the JSON body (Cant paste JSON body here because of character limit):
http://kolam.vicz.in:7890/games_gifs/
I am parsing the above set of JSONObjects and converting them to Java objects. Below is my code of parsing this JSON body.
private void getGameList() {
StringRequest request = new StringRequest(Request.Method.GET, gameUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject mainObject = new JSONObject(response);
JSONArray gamesArray = mainObject.getJSONArray("TracingGames");
Log.e(TAG, "gameArray length:" + gamesArray.length());
for (int i = 0; i < gamesArray.length(); i++) {
JSONObject obj = gamesArray.getJSONObject(i);
for (String str : getKeys(obj)) {
Log.e(TAG, str);
if (str.equalsIgnoreCase("kolam")) {
/*Section for Learn and Kolam Tracing games start*/
//TODO: Need to add the game names to the object (Need server side implementation as well)
KolamTracingGames kolamTracingGames = new KolamTracingGames();
kolamTracingGames.setKolamGifPath(obj.getString("path"));
kolamTracingGames.setKolamLevel(Integer.parseInt(str));
kolamTracingGames.setKolamGameName("Kolam Tracing");
kolamTracingGames.setX(getXCoordinates(obj));
kolamTracingGames.setY(getYCoordinates(obj));
kolamObjects.add(kolamTracingGames);
break;
} else if (str.equalsIgnoreCase("level")) {
LearnTracingGames learnTracingGames = new LearnTracingGames();
learnTracingGames.setLearnGameGifPath(obj.getString("path"));
learnTracingGames.setLearnGameLevel(Integer.parseInt(str));
learnTracingGames.setGameName("Learn Game");
learnTracingGames.setX(getXCoordinates(obj));
learnTracingGames.setY(getYCoordinates(obj));
learnGameObjects.add(learnTracingGames);
Log.e(TAG, learnGameObjects.size() + "");
break;
}
}
}
if (gameType.equalsIgnoreCase("Trace the Kolam")) {
kolamTraceAdapter = new KolamTraceAdapter(getActivity());
kolamTraceAdapter.getGameList(kolamObjects);
recyclerView.setAdapter(kolamTraceAdapter);
} else if (gameType.equalsIgnoreCase("Learn")) {
learnGameAdapter = new LearningGameAdapter(getActivity());
learnGameAdapter.getGameList(learnGameObjects);
Log.e(TAG, "learngameobject size:" + learnGameObjects.size());
recyclerView.setAdapter(learnGameAdapter);
Log.e(TAG, "Learn games");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, error.getMessage());
if (getActivity() != null) {
Alerter.create(getActivity())
.setTitle(R.string.warning)
.setText(R.string.network_error)
.setDuration(2000)
.setBackgroundColorRes(R.color.dot_dark_screen1)
.show();
}
}
});
request.setTag(TAG);
request.setRetryPolicy(new DefaultRetryPolicy(30000, 5, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
AppController.getInstance().addToRequestQueue(request);
My problem is there are 8 level type objects and 4 kolam objects (Please refer the JSON body for clarity). I am having two separate POJO classes for them. I am able to parse the JSON body properly but when I am trying to create Java objects of those JSONObjects the inner most for loop is not running completely. Its stopping after 1 loop.
the inner for loop is not getting executed completely (executing only once but should get executed more then 12 times) if I am doing this (Creating Java Objects):
for (int i = 0; i < gamesArray.length(); i++) {
JSONObject obj = gamesArray.getJSONObject(i);
for (String str : getKeys(obj)) {
Log.e(TAG, str);
if (str.equalsIgnoreCase("kolam")) {
/*Section for Learn and Kolam Tracing games start*/
//TODO: Need to add the game names to the object (Need server side implementation as well)
KolamTracingGames kolamTracingGames = new KolamTracingGames();
kolamTracingGames.setKolamGifPath(obj.getString("path"));
kolamTracingGames.setKolamLevel(Integer.parseInt(str));
kolamTracingGames.setKolamGameName("Kolam Tracing");
kolamTracingGames.setX(getXCoordinates(obj));
kolamTracingGames.setY(getYCoordinates(obj));
kolamObjects.add(kolamTracingGames);
break;
} else if (str.equalsIgnoreCase("level")) {
LearnTracingGames learnTracingGames = new LearnTracingGames();
learnTracingGames.setLearnGameGifPath(obj.getString("path"));
learnTracingGames.setLearnGameLevel(Integer.parseInt(str));
learnTracingGames.setGameName("Learn Game");
learnTracingGames.setX(getXCoordinates(obj));
learnTracingGames.setY(getYCoordinates(obj));
learnGameObjects.add(learnTracingGames);
Log.e(TAG, learnGameObjects.size() + "");
break;
}
}
}
the getKeys(JSONObject) method is below:
private static String[] getKeys(JSONObject firstJSONObject) {
Iterator keysToCopyIterator = firstJSONObject.keys();
List<String> keysList = new ArrayList<>();
while (keysToCopyIterator.hasNext()) {
String key = (String) keysToCopyIterator.next();
keysList.add(key);
}
return keysList.toArray(new String[keysList.size()]);
}
But If I avoid creating objects inside the for loop then the inner for loop runs completely.
But If I avoid creating objects inside the for loop then the inner for
loop runs completely.
Integer.parseInt("level") or Integer.parseInt("kolam") which is clearly a crash
Explanation
when your any of if (str.equalsIgnoreCase("kolam")) or else if (str.equalsIgnoreCase("level")) { matches then
you clearly have a crash here , Integer.parseInt(str) because str will either be level or kolam which are clearly not integers
Solution : Don't use str instead fetch the values
if (str.equalsIgnoreCase("kolam")) {
//... code
kolamTracingGames.setKolamLevel(obj.optInt(str));
//... code ^^^^^^^^^^^^^^^
break;
} else if (str.equalsIgnoreCase("level")) {
//... code
learnTracingGames.setLearnGameLevel(obj.optInt(str));
//... code ^^^^^^^^^^^^^^^
break;
}

Android: JSONObject with volley response

Im trying to download data from a server in the form of a JSON object, parse that object then use the data elsewhere in my app.
Ive created a class which downloads the data (confirmed with a Log.v statement)
The trouble is that i want to display the results in a RecyclerView and the List of objects that i generate after parsing the JSON response does not get generated until after the adapter method is called from my main class.
So my question is, given the code below, how can i ensure that the on response method only exits once the parseResponse method has finished. Currently i am returning the (Null) _releaseList from my requestAndPareseReleaseList method.
public class ParseReleaseJSON extends JSONObject {
String _url;
List<ReleaseInfo> _releaseList = Collections.emptyList();
ParseReleaseJSON(String url) {
super();
_url = url;
}
public List<ReleaseInfo> requestAndParseReleaseList(Context _context){
JsonObjectRequest jsObReq = new JsonObjectRequest(Request.Method.GET, _url, (String) null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
releaseList = parseResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.v("err", "nosuccess");
}
});
MySingleton.getInstance(_context).addToRequestQueue(jsObReq);
return _releaseList;
}
private List parseResponse(JSONObject response) {
List<ReleaseInfo> list = new ArrayList<>();
if(response == null || response.length() == 0){
return list;
}
try {
if(response.has("results")){
JSONArray resultsArray = response.getJSONArray("results");
for(int i = 0, j = 6; i < j; i++){
ReleaseInfo release = new ReleaseInfo();
JSONObject tempObj = resultsArray.getJSONObject(i);
release.title = tempObj.getString("title");
release.date = tempObj.getString("date");
list.add(release);
}
return list;
}
} catch (JSONException e) {
e.printStackTrace();
}
return list;
}
}

Android - Cannot refer to a non-final variable test inside an inner class defined in a different method

I'm currently creating an app utilizing Facebook's Android SDK. Below is the attached code:
private void checkIfPostLiked(final String post_id) {
String isLiked = null;
new Request(Session.getActiveSession(), post_id + "/likes/", null,
HttpMethod.GET, new Request.Callback() {
#Override
public void onCompleted(Response response) {
try {
JSONObject json;
json = new JSONObject(response.getRawResponse());
JSONArray jArray = json.getJSONArray("data");
for (int i = 0; i < jArray.length(); i++) {
user_like_name = jArray.getJSONObject(i)
.get("name").toString();
if (user_like_name.equals(user_me.getName())) {
isLiked= "true";
}
else{
isLiked = "false";
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Get message data
}
}).executeAsync();
}
I would like to return the string isLiked, and return it, but the issue is that I keep on getting Cannot refer to a non-final variable isLiked inside an inner class defined in a different method. I have to use this method (checkifPostLiked) as a function in another iteration within a loop, therefore putting the variable isLiked as member variable would not work as well. I really hope that anyone could help me on this!
You need to initialize isLiked and finalize it:
final String isLiked = new String();
/* Rest of the code remains the same. */
new Request(Session.getActiveSession(), post_id + "/likes/", null,
HttpMethod.GET, new Request.Callback() {
....
....
}

Categories