I have following 2 class
class CallNetworkMethod extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... params) {
if (TwitterUtils.isAuthenticated(prefs)) {
sendTweet();
} else {
Intent i = new Intent(getApplicationContext(), TwPrepareRequestTokenActivity.class);
i.putExtra("tweet_msg",getTweetMsg());
startActivity(i);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//updateLoginStatus();
loginStatus.setText("Logged into Twitter : " + TwitterUtils.isAuthenticated(prefs));
}
}
====================================================
public class TwitterUtils {
static ArrayList<String> friens=null;
public static boolean isAuthenticated(SharedPreferences prefs) {
String token = prefs.getString(OAuth.OAUTH_TOKEN, "");
String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, "");
AccessToken a = new AccessToken(token,secret);
Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(TwConstants.CONSUMER_KEY, TwConstants.CONSUMER_SECRET);
twitter.setOAuthAccessToken(a);
try {
**twitter.getAccountSettings();**
return true;
} catch (TwitterException e) {
return false;
}
}
}
I got the exception when running this code(networkonmainthreadexception).I debug this code and found the location where exception come out. It is twitter.getAccountSettings(); .I think this method should run inside a AsynTask but i dont know how to do that.
Currently you are calling TwitterUtils.isAuthenticated(prefs) in onPostExecute because onPostExecute always execute on UI thread then you are getting networkonmainthreadexception exception .
to avoid this issue use a Boolean Flag to get return from doInBackground and show it in TextView in onPostExecute as:
class CallNetworkMethod extends AsyncTask<Void, Void, Void>
{
public static boolean status=false;
#Override
protected Void doInBackground(Void... params) {
status=TwitterUtils.isAuthenticated(prefs);
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//updateLoginStatus();
loginStatus.setText("Logged into Twitter : " + status);
}
}
the problem is that you're using the AsyncTask wrong.
The idea for the onBackground returning a value and the onPostExecute receiving a result is to pass to the UI thread something that was done on the background thread.
Something like that:
change the class CallNetworkMethod extends AsyncTask<Void, Void, Void> to
class CallNetworkMethod extends AsyncTask<Void, Void, Boolean>
change the protected Void doInBackground(Void... params) { to
protected Boolean doInBackground(Void... params) {
Boolean result = TwitterUtils.isAuthenticated(prefs);
if (result) {
sendTweet();
} else {
Intent i = new Intent(getApplicationContext(), TwPrepareRequestTokenActivity.class);
i.putExtra("tweet_msg",getTweetMsg());
startActivity(i);
}
return result;
}
and change the protected void onPostExecute(Void result) { to
protected void onPostExecute(Boolean result) {
loginStatus.setText("Logged into Twitter : " + result.toString());
}
Note that this method blocks waiting for a network response, so do not call it in a UI thread.
This is what is suggested when using:
facebook.request("me");
Same might be the case with:
twitter.getAccountSettings();
So, just like other Network connections, which you call using AsyncTasks, call this in some AsyncTask.
Okay, the Error might be here:
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//updateLoginStatus();
loginStatus.setText("Logged into Twitter : " + TwitterUtils.isAuthenticated(prefs));
}
You are calling TwitterUtils.isAuthenticated(prefs) in onPostExecute();
Your first call to isAuthenticated() is correctly placed in the AsyncTask. However, when you use:
loginStatus.setText("Logged into Twitter : " + TwitterUtils.isAuthenticated(prefs));
in your onPostExecute(), you're calling a networking method on the UI thread again, as onPostExecute() is run on the UI thread.
Remove this line, or store the result locally from doInBackground() and use it here.
Related
In my application, there are multiple asynctasks. Please let me know why doInBackground of an asynctask sometimes does not getting called. Its onPreExecute method gets called. Is there any issue because of multiple asynctasks or something else?
/* ASync class for test table */
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
If your project has multiple asynctasks you must check that there is a limit of asynctasks that can be executed. When you create a new AsyncTask it will be added on a Pool and will be execute only when is possible.
Check this answer:
Multitasking on android
And the docs: ThreadPoolExecutor
Here is an example on how properly handle multiple AsyncTasks AsyncTaskManager
OnPreExecute() gets called on the UI thread and doInBackground() is called on the background thread.
There is one dedicated background thread for the async task. This behaviour can be changed if you want to.
http://android-er.blogspot.in/2014/04/run-multi-asynctask-as-same-time.html
Now, say you have multiple instances of async task and I'm assuming you are calling execute() to run the async tasks. This will trigger all the preExecute immediately since UI thread is free but for the doInBackground it will triggered one by one. Hence it may take some time for the next async task to start.
doInBackground should run on a loop using a Boolean to check before execution. Before your Task is being executed, set a global boolean (may be true/false) depends on which you prefer and values add on thread should call runOnUiThread.
startExect = true;
new TestAsynch().execute();
then change this
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
to this
public class TestAsynch extends AsyncTask<String, Void, String> {
String result1 = null;
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
result1=API_Manager.getInstance().sendTestData(userName);
while (startExecute) {
Thread exe = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5);
}
catch( Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
if(result1 != null) {
// save in db
}
}
});
}
}); exe.start();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
I have a class AsyncCallWS that get content from webservice. It worked well. However, I want to get result in the class AsyncCallWS, namely returnServer string in the MainActivity . Could you help me to solve it?
public class MainActivity extends Activity {
String resultRegister;
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btnRegister =(Button) findViewById(R.id.btnRegister);
btnRegister.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
new AsyncCallWS().execute("123");
Log.d("DDD",resultRegister);
if(resultRegister.equals("")) {
Log.d("D", "OK");
}
else
{
Log.d("E", "False");
}
}
});
}
private class AsyncCallWS extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
Log.i(TAG, "doInBackground");
String id_num = params[0];
//toast(id);
String url_registerID="server path"+id_num ;
try {
String returnServer=getStringContent(id);
Log.d("D",returnServer);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
Log.i(TAG, "onPostExecute");
}
#Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
#Override
protected void onProgressUpdate(Void... values) {
Log.i(TAG, "onProgressUpdate");
}
}
Remove 3rd parameter Void from this AsyncTask<String, Void, Void>
and replace it with String, i.e;
private class AsyncCallWS extends AsyncTask<String, Void, String>
After changing you'll get compilation errors in your doInBackground().. just change the return type from Void to String
protected String doInBackground(String... params)
Now you can get the String returned by this method in onPostExecute(String result)
The String result here is the String which is returned by doInBackground()
*EDIT *
public class MainActivity extends Activity {
String resultInActivity;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new AsyncCallWS().execute("123");
//How to get respond from AsyncCallWS
}
private class AsyncCallWS extends AsyncTask<String, Void, Void> {
#Override
protected String doInBackground(String... params) {
Log.i(TAG, "doInBackground");
String id_num = params[0];
//toast(id);
String url_registerID="server path"+id_num ;
try {
String returnServer=getStringContent(id);
Log.d("D",returnServer);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return returnServer;
}
#Override
protected void onPostExecute(String result) {
Log.i(TAG, "onPostExecute");
resultInActivity = result;
if(resultRegister.equals("")) {
Log.d("D", "OK");
}
else
{
Log.d("E", "False");
}
}
#Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
#Override
protected void onProgressUpdate(Void... values) {
Log.i(TAG, "onProgressUpdate");
}
} // Asyntask ends
} // activity ends
The response from AsyncTask is produced in onPostExecute() from there you can perform tasks based on the response etc.
I highly recommend you read the AsyncTask Life Cycle
private class AsyncCallWS extends AsyncTask
Replace the third parameter with String which results doInBackground return String and corresponding postExecute method parameter as String
protected String doInBackground(String... params)
protected void onPostExecute(String result)
In Order to get it on MainActivity you have to do the following Steps
Create an Interface anywhere you want to and declare a method of any name which should have parameter of type String
interface ResponseHandler
{
void onResponse(String result)
}
In the MainActivity you have to implement that interface and you will
get the data here in this method
ResponseHandler handler = new ResponseHandler(){
#override
public void onResponse(String result)
{
// enter code here
}
};
After implementing this interface you can provide the instance of it to the AsyncTask constructor.
AsyncTask task = new AsyncTask(handler);
You will get the reference of ResponseHandler in AsyncTask
public AsyncTaskClass(ResponseHandler handler)
{
this.handler = handler
}
//enter code here
void onPostExecute(String result)
{
handler.onResponse(result)
}
This way you will get the result in your MainActivity.
Could anyone help me on following questions.
1) onPostExecute - Toast.make while in background i am sending HttpRequest.
0nCraeteBunle - execute() ; startNewActivity
showing error. AsycTask# Runtime Exception .
While commenting Http request in background, no error is showed.
here, how can i know that http Request and reply finished , so that i can start my new Activity.
2) how to get HttpParams. Sending from TIBCO BE (As event with properties)
3) What if i am recieving JSONObject, JAVAObject, Integer other than String in onPostExecute. unable to override .
Try this,
protected class GetTask extends AsyncTask<Void, Void, Integer> {
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(MainActivity.this,
"Loading", "Please wait");
}
#Override
protected Integer doInBackground(Void... params) {
// TODO Auto-generated method stub
//call ur HttpRequest
httpRequest();
return 0;
}
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
if (mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
mHandler.sendEmptyMessage(0);
}
}
Handler mHandler = new Handler() {
public void handleMessage(Message Msg) {
if (Flag) {
//Add ur stuff
}else{
}
And then in ur method set Flag value
public void httpRequest() {
// TODO Auto-generated method stub
String URL ="ADD UR URL";
try {
JSONObject ResponseObject = mAPIService.CallAPI(
YourActivity.this, URL);
String status = ResponseObject.getString("status");
Flag = true;
} catch (Exception err) {
Flag = false;
}
}
I'm trying to implement async on Android but it keeps crashing my app, the code in doInBackground works if I put it in the oncreate so that i know that It works
any help is greatly appreciated
thanks
here's my code :
public class accueilEco extends Activity
{
String[] param = new String[5];
TextView nom;
TextView prenom;
ProgressDialog mDialog;
Context ctxt;
TelephonyManager tm;
connectEco ce;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nom = (TextView) findViewById(R.id.user);
ctxt = getBaseContext();
tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
new chargerParam().execute();
}
public class chargerParam extends AsyncTask<Void, Void, Void> {
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
}
#Override
protected Void doInBackground(Void... params) {
try
{
ce =new connectEco();
param = ce.recupereParam(tm.getDeviceId());
if(String.valueOf(param[4]) == String.valueOf(1))
{
Toast.makeText(ctxt, "Paramétres chargées" , Toast.LENGTH_LONG).show();
//setContentView(R.layout.home);
nom.setText(param[1]+" "+ param[2]+" - "+param[3]);
}
else
{
Toast.makeText(ctxt, "=> login" , Toast.LENGTH_LONG).show();
}
}
catch(Exception ex)
{
Toast.makeText(ctxt, "erreur" , Toast.LENGTH_LONG).show();
}
return null;
}
}
}
You cannot access UI objects from another thread than the UI thread. The code:
nom.setText(param[1]+" "+ param[2]+" - "+param[3]);
will throw the exception.
You can access the UI elements when you are in onPreExecute() or onPostExecute(Result). Accessing UI elements while youre in doInBackground, it'll result in exception.
To "fix" this you need to read through and understand the AsyncTask implementation. Instead of declaring your background task by AsyncTask<Void, Void, Void> you can provide an "result type" that the can be posted from the doInBackground method to the onPostExecute method (on the UI thread). AsyncTask<Void, Void, String> (the String type).
You would have to do something like this:
#Override
protected void onPostExecute(String result) {
if (result != null)
nom.setText(result);
// else show toast
}
#Override
protected String doInBackground(Void... params) {
try {
String[] param = new connectEco().recupereParam(tm.getDeviceId());
if (String.valueOf(param[4]) == String.valueOf(1))
return param[1]+" "+ param[2]+" - "+param[3];
} catch(Exception ex) {
// ignore and return null
}
return null;
}
Okay, this has me confused once again. I am trying to either A: set a golbal variable, which i can do or B: retieve a variable from my AsyncTask. I have set can set the golbal variable from asynctask which is fine, but the activity calls it before it is set with the asynctask.
So therefore I need the application to finsh the AsyncTask before calling the golbal variable.
new createUser().execute();
Log.i("res", "After: " + Boolean.toString(MyProperties.getInstance().valut));
private class createUser extends AsyncTask<Void, Void, Boolean> {
ProgressDialog dialog = ProgressDialog.show(MainActivity.this, "",
"Creating User...", true);
Toast toast = Toast.makeText(getApplicationContext(), "",
Toast.LENGTH_SHORT);
#Override
protected Boolean doInBackground(Void... params) {
// TODO Auto-generated method stub
if (db.createUser(nameU.getText().toString(), userU.getText()
.toString(), emailU.getText().toString(), passU.getText()
.toString()) == false) {
return false;
} else {
return true;
}
}
protected void onPreExecute() {
dialog.show();
}
protected void onPostExecute(Boolean result) {
dialog.dismiss();
if (!result) {
toast.setText("User already exists!");
toast.show();
res = result;
MyProperties.getInstance().valut = res;
Log.i("res", Boolean.toString(MyProperties.getInstance().valut));
} else {
toast.setText("Success");
toast.show();
res = result;
MyProperties.getInstance().valut = res;
Log.i("res", Boolean.toString(MyProperties.getInstance().valut));
}
}
}
Work with your global variable in onPostExecute method of your AsyncTask. You need to implement it in your AsyncTask's child. This method is called then all work is done.
EDIT
private class createUser extends AsyncTask<Void, Void, Boolean> {
ProgressDialog dialog;
#Override
protected Boolean doInBackground(Void... params) {
// TODO Auto-generated method stub
if (db.createUser(nameU.getText().toString(), userU.getText()
.toString(), emailU.getText().toString(), passU.getText()
.toString()) == false) {
return false;
} else {
return true;
}
}
protected void onPreExecute() {
dialog = ProgressDialog.show(MainActivity.this, "", "Creating User...", true);
dialog.show();
}
protected void onPostExecute(Boolean result) {
dialog.dismiss();
Toast.makeText(
getApplicationContext(),
result?"Success":"User already exists!",
Toast.LENGTH_SHORT).show();
MyProperties.getInstance().valut = result
Log.i("res", Boolean.toString(MyProperties.getInstance().valut));
}
}
Two issues:
Java does not really have any global variables. The closest it has are static class variables. Since you haven't shown your declared variable, I can't say what you've really implemented.
Every AsyncTask has a onPostExecute(..) method you can override that runs in the original thread/Looper after doInBackground(..) has completed. Override this to do things like Update the UI thread.