Getting JSONObject from doInBackround() of AsynchTask and passing to main class - android

I am trying to use the json object outside of the Async task but my class doesn't recognize it.
How do I pass the JSONObject to the outside of the Async task?
The only thing I could find was trying to use onProgressUpdate() to pass the object but I tried implementing and the object would come up blank :(.
Any help would be appreciated, thank you.
Here is my class:
public class NewHomepage extends Activity {
public static String url = "http://www.alkouri.com/android/SQL.php?username=";
public static String usernamefromlogin;
public static TextView errorchecking;
public static JSONArray user = null;
//JSON Node Names
public String TAG_USER = "users";
public String TAG_FIRST = "first";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.reshomepage);
//get data from previous screen
Intent intent = getIntent();
getIntent().getExtras();
//convert intent (intent) to string called "usernamefromlogin"
//error checking in log cat to see value of "usernamefromlogin"
usernamefromlogin = intent.getExtras().getString("username2");
Log.d("log usernamefromlogin", usernamefromlogin);
//take the string "url" and add string "usernamefromlogin" after it
//error checking in log cat to see value of url5
String url5 = url.concat(usernamefromlogin);
Log.d("log url5", url5);
//start asynch task
class PostTask2 extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}//end PreExecute
#Override
protected String doInBackground(String... params) {
//pass url from outside class to inside this class
String url5 = params[0];
//Creating new JSON Parser
JSONParser jParser = new JSONParser();
// Getting JSON from URL
JSONObject json = jParser.getJSONFromUrl(url5);
return null;
}//end doInBackground
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}//end onProgressUpdate
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}//end onPostExecute
}//end Async task
//execute the Async task
new PostTask2().execute(url5);
}//end oncreate
#Override
public void onBackPressed() {
// do nothing on back press
}
}//end class

You have to pull your asynctask out of your onCreate method and insert it as a nested class in NewHomepage.
Now, you can return a JSONObject from doInBackground() as shown in the code below. Note the AsncTask.
This is nice to learn something (the hard way) about activity life-cycle and memory leaks (I'm serious, try it, just for practice sake). For a real application however i'd highly recommend a Rest client library like Volley.
public class NewHomepage extends Activity {
// ... your activity code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new PostTask2().execute(url5);
}
class PostTask2 extends AsyncTask<String, String, JSONObject> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}//end PreExecute
#Override
protected String doInBackground(String... params) {
//pass url from outside class to inside this class
String url5 = params[0];
//Creating new JSON Parser
JSONParser jParser = new JSONParser();
// Getting JSON from URL
JSONObject json = jParser.getJSONFromUrl(url5);
return json;
}//end doInBackground
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}//end onProgressUpdate
#Override
protected void onPostExecute(JSONObject result) {
// HERE, this is running on the main thread.
// You can do whatever you need to do with your JSONObject.
// Maybe call setData(result) but be careful, the user might have left this activty already!
// And the View might have been already destroyed, so watchout for null-pointer-exceptions
}//end onPostExecute
}
}

You need to put AsyncTask calss outside the onCreate method and call it from inside onCreate method.
P.S. However, as in the comment, post your json response and tell us what you want to parse from the response. On top of that, you need to use HTTP or Rest Client to query the server and get response.
EDIT
To know how you can make a request to server, go through this tutorial or you may also go through this tutorial.

You can return the JSONObject in your onPostExecute as below:
class PostTask2 extends AsyncTask<String, String, JSONObject> {
..............................
#Override
protected String doInBackground(String... params) {
//pass url from outside class to inside this class
String url5 = params[0];
//Creating new JSON Parser
JSONParser jParser = new JSONParser();
// Getting JSON from URL
JSONObject json = jParser.getJSONFromUrl(url5);
return json;
}//end doInBackground
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}//end onProgressUpdate
#Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
}//end onPostExecute
}//end Async task

Related

Finish procedure before starting a new one

I am beginner in Android and I need some help. So, I have a procedure with sub-procedures inside. How can I finish one before starting a new one. Here is a code to better understand:
public void onCellLocationChanged(CellLocation lokacija) {
super.onCellLocationChanged(lokacija);
location = (GsmCellLocation) Phone.getCellLocation();
textCellId.setText(String.valueOf(location.getCid() % 65536));
textCellLac.setText(String.valueOf(location.getLac()));
String JSON_URL_string=JSON_URL + "?cellid=" + String.valueOf(location.getCid()%65636);
getJSON(JSON_URL_string);
myJSONString = textCellNameSakriven.getText().toString();
ParseJSON(myJSONString);
}
Problem is that myJSONString is empty, cause textCEllNameSkriven is also empty. That textView textCellNameSkriven is made when getJSON(JSON_URL_string) is finished. If I run debugger and go step by step, app goes directly from getJSON(JSON_URL_string) row to the next one and the next etc
Edit: Maybe the problem is that onPostExecute is not finished before starting ParseJSON. Here is also a code for getJSON:
private void getJSON(String url) {
class GetJSON extends AsyncTask<String, Void, String> {
ProgressDialog loading;
#Override
protected void onPreExecute() {
super.onPreExecute();
loading = ProgressDialog.show(MainActivity.this, "Please Wait...", null, true, true);
}
#Override
protected String doInBackground(String... params) {
String uri = params[0];
BufferedReader bufferedReader = null;
try {
URL url = new URL(uri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder();
bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String json;
while ((json = bufferedReader.readLine()) != null) {
sb.append(json + "\n");
}
return sb.toString().trim();
} catch (Exception e) {
return null;
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loading.dismiss();
textCellNameSakriven.setText(s);
}
}
GetJSON gj = new GetJSON();
gj.execute(url);
}
Since you are running a async task it practically runs on a different thread, so your getJson method need not wait for post execute and can return after starting the async task, so you can never be sure in this way that parseJson gets executed after textView is populated. You are running into classic race condition issue.
Your issue could be easily solved, if you have a callback which is called after postExecute is done, and you can handle parseJson there
So, something simple like , create interface MyCallback
public interface MyCallback {
public OnReadJsonDone();
}
Let your activity implement this MyCallback
public MainActivity implements MyCallback
{
...........
#Override
public OnReadJsonDone(){
parseJson();
}
Now change signature of getJson to
getJSON(string json, final MyCallback callback) {
Now in onpostexecute
//call OnReadJsonDone
callback.OnReadJsonDone()
So, all you now need is while calling getJSon pass this as second param
getJSON(JSON_URL_string,this);
Haven't tested this but you get the idea

android - AsyncTask not reaching onPostExecute() - "The application may be doing too much in its main thread"

I have a Fragment in which I want to parse a JSON and create an ArrayList with some of its attributes and then put the ArrayList's data to a Spinner. However, I do not know if I am doing the AsyncTask as it I should.
Everytime I try a new way to parse the JSON from a URL in my Fragment Activity either the app crashes with "Unfortunately, the app has stopped" message or the Spinner stays empty. I verified with Logs that I never reach the onPostExecute() method on the AsyncTask.
Questions:
- What am I doing wrong?
- Should I be using AsyncTask?
My code:
private class LoadResources extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.v(TAG, "pre-execute");
}
// Call after onPreExecute method
#Override
protected String doInBackground(String... urls) {
Log.v(TAG, "background");
Log.v(TAG, urls[0]);
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
try {
URL u = new URL(urls[0]);
BufferedReader in = new BufferedReader(new InputStreamReader(u.openStream(), Charset.forName("UTF-8")));
StringBuilder sb = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
// the above parsing works, I've tested
JsonParser parser = new JsonParser();
JsonElement elem = parser.parse(sb.toString());
JsonArray array = elem.getAsJsonArray();
for (int i = 0; i < array.size(); i++) {
JsonElement elem1 = array.get(i);
JsonArray tmpArr = elem1.getAsJsonArray();
for (JsonElement elem2 : tmpArr) {
elem2.getAsJsonObject().getAsJsonPrimitive().getAsString());
myArrayList.add(elem2.getAsJsonObject().getAsJsonPrimitive("name").toString());
return urls[0];
}
protected void onPostExecute(String params) {
Log.v(TAG, params);
}
}
On the onCreateView:
LoadResources loader = new LoadResources();
loader.execute("http://localhost:5000/avalidpath);
text = (AutoCompleteTextView) rootView.findViewById(R.id.nomeAluno);
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity().getApplicationContext(),
android.R.layout.simple_spinner_dropdown_item, myArrayList);
text.setAdapter(adapter);
text.setThreshold(3);
Right now the app stops working when I swipe to this fragment.
Thanks in advance, guys.
Actually you should do the heavy work in doInBckground method.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter. Doc here
EDIT:
class LoadResources extends AsyncTask<String, Void, ArrayList<String>> {
Context context;
public LoadResources(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... urls) {
...
return myArrayList;
}
protected void onPostExecute(ArrayList<String> params) {
((YourActivity)context).setMyAdapter(params);
}
}
In your Activity (fragment or whatever) :
public void setMyAdapter(ArrayList<String> params) {
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity().getApplicationContext(),
android.R.layout.simple_spinner_dropdown_item, myArrayList);
text.setAdapter(adapter);
}
onPostExecute is done on the UI thread. You have way too much work on it. Everything that isn't directly effecting a UI element should be done in doInBackground. Right now your doInBackground is doing nothing.
Move whole code from onPostExecute to doInBackground. You can use publishProgress(...); and onProgressUpdate to add items to list. Or create local list in AsyncTask and addAll items to your global List in onPostExecute

Return string from Asynctask

i am trying to parse a jsonObject, but i cant get the result out of doInBackground into onPostExecute
Here is my AsyncTask code:
private class GetContacts extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(MyActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
String auth2 = jsonObj.getString("auth");
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
#Override
protected void onPostExecute(Void auth2) {
super.onPostExecute(auth2);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
Toast.makeText(getApplicationContext(), "String retrived:" + auth2, Toast.LENGTH_SHORT).show();
}
}
I know its propably because i have return null there, but when i make return string then i get error.
I know in fact that jsonStr holds json data, i can see it in log:
Response:﹕ > {"user_info":{"auth":0}}
I put this code together from tutorials, thats why i dont completly understand it.
My goal is to see if auth is 0 or 1.
cant get the result out of doInBackground into onPostExecute
To return auth2 String from doInBackground :
1. Change return type of doInBackground method from Void to String:
#Override
protected String doInBackground(Void... arg0) {
}
2. Change AsyncTask last generic type from Void to String :
private class GetContacts extends AsyncTask<Void, Void, String>
3. Return auth2 from doInBackground :
String auth2 = jsonObj.getString("auth");
return auth2;
4. Change onPostExecute parameter type from Void to String :
#Override
protected void onPostExecute(String auth2) {
super.onPostExecute(auth2);
//...
Toast.makeText(getApplicationContext(),
"String retrived:" + auth2, Toast.LENGTH_SHORT).show();
}
read the documentation:
http://developer.android.com/reference/android/os/AsyncTask.html
private class GetContacts extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... arg0) {
...
return "askdjalskdj";
}
#Override
protected void onPostExecute(String auth2) {
Log.i("Output", auth2);
}
}
See the params I have set in the Generic implementation of Asynctask , see the defined return value from doInBackground and the Parameter type of onPostExecute
AsyncTask's generic types The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the
background computation.
Result, the type of the result of the
background computation.
Not all types are always used by an
asynchronous task. To mark a type as unused, simply use the type Void:
private class MyTask extends AsyncTask { ... }

How to parse JSON from URL every n seconds using AsyncTask within a fragment?

I want to parse JSON every few seconds. My idea is by constantly parsing it to see if there are some changes in it and if there are to get them and update my views (mostly TextViews). I have a Fragment, called MyFragment. In its onCreateView I am executing the following: new MyTask().execute(myJSONUrl);. Some code:
class MyTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
//getJSONString(String url) - my method for getting the JSON from URL
return getJSONString(params[0]);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result == null || result.length() == 0) {
Log.w(TAG," JSON IS **null** ");
Toast.makeText(getActivity().getApplicationContext(), "JSON IS NULL", Toast.LENGTH_SHORT).show();
} else {
try{
JSONObject root = new JSONObject(result);
// Here i get what i need from the JSONObject and everything works fine.
} catch (Exception e) {
e.printStackTrace();
}
}
Now how to parse the JSON from URL every n seconds? I have tried using ScheduledExecutorService, Timer and Thread but nothing seems to work. Thanks in advance :-)
When you really throw the battery concerns out of the window:
Change class MyTask extends AsyncTask<String, Void, String> to class MyTask extends AsyncTask<String, String, Void>
Do the following:
protected String doInBackground(String... params) {
//getJSONString(String url) - my method for getting the JSON from URL
while(isCancelled() == false) {
try {
Thread.sleep(1000* 5); // only do this every 5 seconds.
} catch (InterruptException ex) {}
publishResult(getJSONString(params[0]));
}
}
public void onResultPublished(String result) {
// stuff that happened in onResult before...
}
You emit strings as a result and handle it in onResultPublished (this method is executed on the UI thread so it's safe to modify ui here).
Don't forget to cancel the asynctask.

Convert android AsyncTask call to a separate class and call from all activities

I am new to android development. I have a AsyncTask function in my application. Calling http request from all activities. Now in each activity I am using the following class to connect to server, in some activities I even called twice !!.
Basically I am a web developer and in such cases we use a single class which can be accessed from entire application(web) and use the common function to do the same activity. The only difference is input and out put will be changed.
My doubt is in this case can I use ( convert) this to such a function or class ?
My assume is
Create an android class ( which can be accessed from all the activities )
Just make the JSON string we need with specific server ( for process in server )
Just pass the created json to the created class and then made the http connect )
Process the returned data from server
Pass that to the corresponding activity
So that I can use the same function for all the activities and I can avoid duplicate query
Can I convert this code to such a manner ?
My Code
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_main);
LogIN loginUser = new LogIN();
LoginUser.execute("");
}
private class LogIN extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
try {
String path = "http://www.domain_name.com/app/checkSession.php";
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost(path);
json.put("access_token", "123456");
post.setHeader("json", json.toString());
StringEntity se = new StringEntity(json.toString());
se.setContentEncoding((Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/* Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent();
String a = convertStreamToString(in);
JSONObject jsono = stringToJsonobj(a);
String passedStringValue = jsono.getString("result");
if(passedStringValue.equals("1")){
flags=1;
//Log.v("TAGG", "Success");
}
else {
flags=0;
//Log.v("TAGG", "Failed !");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialogue("Login Processing", "Loading");
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
}
#Override
protected void onPostExecute(String result) {
if(flags.equals(1)){
Itent homepage = new Intent(MainActivity.this, RegisterDevice.class);
startActivity(homepage);
finish();
}
else {
Intent homepage = new Intent(MainActivity.this, LoginActivity.class);
startActivity(homepage);
finish();
}
super.onPostExecute(result);
}
}
}
Please any one help/advise
Thanks in advance
Extract your class to a different file and make it public
public class LogIN extends AsyncTask<Object, Integer, String> {
private ILoginListener listener;
#Override
protected String doInBackground(Object... arg0) {
try {
this.listener = (ILoginListener) arg0[0];
//You can also send the url in the obj array
String theUrl = (String) arg0[1];
String path = "http://www.domain_name.com/app/checkSession.php";
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost(path);
json.put("access_token", "123456");
post.setHeader("json", json.toString());
StringEntity se = new StringEntity(json.toString());
se.setContentEncoding((Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/* Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent();
String a = convertStreamToString(in);
JSONObject jsono = stringToJsonobj(a);
String passedStringValue = jsono.getString("result");
if(passedStringValue.equals("1")){
flags=1;
//Log.v("TAGG", "Success");
}
else {
flags=0;
//Log.v("TAGG", "Failed !");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialogue("Login Processing", "Loading");
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
}
#Override
protected void onPostExecute(String result) {
listener.logInSessionCheckListener(flag.equals(1));
super.onPostExecute(result);
}
}
Regarding your other question, I normally have an interface for that, something like this:
public interface ILoginListener {
public void logInSessionCheckListener(SomeNeeded Value);
}
I implement the interface in the class where i need the postExecute result and in the overriden method you can to what you want with the result of your task.
Your class where you user it will look something like this:
public class SomeClass implements ILoginListener {
//Call it like this from any class:
LogIN loginTask = new LogIn();
Object[] someParams = new Object[2];
//add the listener
someParams[0] = SomeClass.this
//add the url
someParams[1] = someUrlString;
loginTask.execute(someParams);
#Override
public void logInSessionCheckListener(SomeNeeded Value){
//do Stuff with your results
}
}
You can do it like make separate class for everything inside doInBackground() method and called it in all activity with passing parameter to
LogIN loginUser = new LogIN(yourparameter);
LoginUser.execute("");
and check parameter in AsyncTask Class constructor like
public LogIN(Myparameter){
// Your data
}
On the other hand you can use this great framework for android : android-query and the async API.
It allows you to perform asynchroneous network tasks from activities and easily work with the results of your requests.
You should use interfaces to implement a callback to your ui activity.
Have a look at this thread, it might be useful:
android asynctask sending callbacks to ui
And your asyntask class should be in a seperate java file with public acces.
And to pass the parametres you simply have to call a new LogIN async Task like this:
new LogIN().execute(urls);
Hope it helped :)
Remember that you can never know when AsyncTask is going to finish. So if you're using this to authenticate users and then perform task X, task Y, or task Z,
then maybe it's better to create a Login helper class
public class LoginHelper {
public boolean login(params){
// Authenticate user and return true if successfull
}
}
and then have in your Activity classes
private class X extends AsyncTask {
#Override
protected String doInBackground(String... sUrl) {
...
boolean authenticated = LoginHelper.login(params...);
if(authenticated == true) {
// Perform task X here...
} else {
// Inform the user that the login failed...
}
}
First of all
You have to pass the context in which you are calling your async task
Sample Code
Login loginTask = new Long(getContext());
loginTask.execute();
You class Login should have a constructor that accepts the Context
Sample Code
public class Login extends AsyncTask<String, Integer, String> {
private Context mContext ;
private ProgressDialog pd;
private Handler handler = new Handler { };
public Login (Context context){
mContext = context ;
}
.....
Then make sure to create the method showDialog inside Login class to show the progress dialog
Note
You can add what ever Constructors you need to customize the behaviour of your Login task
for example : pass boolean parameter to tell that the Login Task is cancelable....
Hope that help you :)

Categories

Resources