I have created an android apps that using async task to call web service,
when authentication fail, user will stop current activity and redirect back to login page.
My problem is when user redirect back to login page, a toast text still showing, this toast text is under async thread onPostExceute() event.
any solution for this problem?
in the webService.cs
catch (UnauthorizedException ua) {
Log.d(tag, ua.getMessage());
Intent intent = new Intent(activity, LoginActivity.class);
if(condition a){
intent.putExtra("toast_text", R.string.a);
}else{
intent.putExtra("toast_text", R.string.b);
}
activity.finish();
activity.startActivity(intent);
}
return null;
then in asyncTask.cs
protected JSONArray doInBackground(String... parameters) {
ConnectivityManager cm =
(ConnectivityManager) SingleFormActivity.this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
if (isConnected) {
}
return null;
}
public void onPostExecute(JSonArray result){
if(result != null){
}else{
Toast.makeText(Something.this, R.string.b, Toast.LENGTH_LONG).show();
}
}
you can Use
Create Toast like
Toast toast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_LONG);
and before calling finish() cancel toast using below code
if (toast != null )
toast.cancel();
Try like this
Return request status from doInBackground.and show toast using that status in onPostExecute
may be there is any syntax error in this code.But i hope it help you
public class AsyncConnectTask extends AsyncTask<Void, Void, Boolean> {
private MyInterface mListener;
public AsyncConnectTask(Context context, String address, String user,
String pass, int port, MyInterface mListener) {
}
#Override
protected Boolean doInBackground(Void... params) {
....
return result;
}
#Override
protected void onPostExecute(Boolean result) {
if (result == true) {
//Show toast here
}else{
}
}
}
In onPause() add below code
if(isFinishing()){
if (toast != null || toast.getView().getWindowVisibility() == View.VISIBLE) {
toast.cancel();
}
}
when authentication fail, user will stop current activity and redirect back to login page.
with your above question, I assume you got two different activity (one for login and another for doing something also showing the toast message. If its correct then before showing the toast check if the activity is finishing if not then show the toast.
if(!isFinishing()){
// show toast
}
http://developer.android.com/reference/android/app/Activity.html#isFinishing%28%29
Related
I have an asynctask and I'm looking to do a wait if the async is taking too long, I'm downloading some data of the database , but I don't want to have the user looping around the progressdialog, I want to set a fixed time, lets say I'm downloading a file but is taking forever, so I tell the user, "hey, check your internet connection and try again" I'm looking to do this with a timer, but I'm kinda stuck, this is where I do my asynctask
private class DownloadFilesTask extends AsyncTask<Void, Void, Void> {
String s;
public DownloadFilesTask(String s){
this.s = s;
}
#Override
protected Void doInBackground(Void... voids) {
DownloadMethod(s);
return null;
}
}
so let's say I want to execute that downloadmethod for a fixed time, 10 or 20 seconds, if the file is not downloaded at that time I return a message to the user saying that he needs to check for hes internet.
You can use handler to run after a definite amount time and maintain a boolean flag which you can update in postExecute function of async task.
In your activity/fragment class:
new Handler().postDelayed(new Runnable(){
public void run(){
//Check whether the flag has been updated or not
},1000)
You can use BroadcastReceiver to listen your internet connection. Here is an example:
public class NetworkControl extends BroadcastReceiver {
static boolean isConnected = false;
#Override
public void onReceive(final Context context, final Intent intent) {
isNetworkAvailable(context);
}
private boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
if(!isConnected){
isConnected = true;
Toast.makeText(context, "You're online!!", Toast.LENGTH_LONG).show();
}
return true;
}
}
}
}
isConnected = false;
Toast.makeText(context, "Connection interrupted.", Toast.LENGTH_LONG).show();
return false;
}
}
Also you need some permissions in AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Then start the service in your activity.
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
receiver = new NetworkControl();
registerReceiver(receiver, filter);
If you are using HttpURLConnection to download the file then you can do something like this:
private class DownloadFilesTask extends AsyncTask<String, Integer, Integer> {
#Override
protected Integer doInBackground(String... ulr) {
URL url = null;
try {
url = new URL(ulr[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setConnectTimeout(2000); //Timeout
//...Other codes for downloading
return 101;
} catch (java.net.SocketTimeoutException e) {
return 102;
} catch (MalformedURLException e) {
return 103;
} catch (IOException e) {
return 104;
}
}
#Override
protected void onPostExecute(Integer result) {
if(result == 102) {
Toast.makeText(getApplicationContext(), "Connection Timeout.", Toast.LENGTH_LONG).show();
}
}
}
First thing I want to say that is, while running downloading task it's not a good practice, to message a user that check your internet connection or
no internet connection. Because in this condition, if user do switch off then on network connection then your downloading task restarts again and takes whole time again. So, avoid this types of messages.
Now about solution, after execute background task you can check your task is running or completed. If it takes too much time
then show a message. For example,
YourBackgroundTask task = new YourBackgroundTask();
task.execute();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (task.getStatus == AsyncTask.Status.RUNNING){
Toast.makeText(this, "Please wait...", Toast.LENGTH_SHORT).show();
}
}
},20000); // time in milisecond
And if you want to repeat this, you can easily re-run handler.
Here is a basic idea you can try if it works
private class DownloadFilesTask extends AsyncTask<Void, Integer, Void> implements TimerTask{
String s;
Timer timer;
Object objectResult;
public DownloadFilesTask(String s){
this.s = s;
timer = new Timer();
}
#Override
protected Void doInBackground(Void... voids) {
objectResult = DownloadMethod();
return null;
}
private Object DownloadMethod() {
//here implement the download logic and return the object
return null;
}
#Override
protected void onProgressUpdate(Integer... progress) {
// your code to update progress
}
public void checkProgress(){
timer.schedule(this,2000);
}
#Override
public void run() {
if (objectResult!=null){
//download completed
}else{
//show dialog here and schedule a task again
timer.schedule(this,2000);
}
}
}
I'm trying to use a AsyncTask to check if internet connection is available and then doing some stuff.
My problem is while the comprobation is being executed I can´t interacting with the UI. The "progressbar" is on front and if I try to click on a button the UI doesn't respond
This is the call to AsyncTask
#Override
public void onStart(){
super.onStart();
AsyncHttpHandler check = new AsyncHttpHandler(**paramaters**);
check.execute("checkshared");
}
This is the code of AsyncTask
public class AsyncHttpHandler extends AsyncTask<String, Integer, String>{
public AsyncHttpHandler(Context c, Intent i, Bundle _data, String _language){
ctx = c;
intent = i;
data = _data;
language = _language;
startClock();
}
public void startClock(){
mDialog = new ProgressDialog(ctx,R.style.MyTheme);
mDialog.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
mDialog.setCancelable(false);
mDialog.show();
}
#SuppressWarnings("unchecked")
#Override
protected String doInBackground(String... peticion) {
String response = "null";
//call to check if internet connection is available
if(Utils.isInternetConn(ctx)){
try {
// do stuff
response = "...";
}
else response = "offline";
return response;
}
}
protected void onPostExecute(String response) {
if(mDialog != null) mDialog.dismiss();
if(!response.equals("offline")){
// do stuff
}
else Toast.makeText(ctx, ctx.getResources().getString(ctx.getResources().getIdentifier(language+"_toast_nointernet", "string", ctx.getPackageName())), Toast.LENGTH_LONG).show();
}
}
And this is the method to check if the internet connection is available:
public static Boolean isInternetConn(Context ctx){
ConnectivityManager connec = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifi = connec.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo mobile = connec.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
boolean conectado = false;
if((wifi != null && wifi.isConnectedOrConnecting()) || (mobile != null && mobile.isConnectedOrConnecting())){
try {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
URL myurl = new URL("http://www.google.com");
URLConnection connection;
connection = myurl.openConnection();
connection.setConnectTimeout(2000);
connection.setReadTimeout(2000);
HttpURLConnection httpConnection = (HttpURLConnection) connection;
int responseCode = -1;
responseCode = httpConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
conectado = true;
httpConnection.disconnect();
}
else {
httpConnection.disconnect();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return conectado;
}
What am I doing wrong?
The problem is not in your AsyncTask calling static method. That will also execute async. Problem is that you are showing progress dialog until your task finishes. And, of course, while your progress dialog is visible you will not be able to interact with the UI. If you want to interact with the UI, show your progress in another way, not with dialog.
You display a progressDialog on top of the screen. The progress dialog takes the UI interaction, so the buttons underneath don't respond. If you use a progress bar in your UI instead of a progress dialog, your buttons will work.
If you want to show the progress of your task to the user, use the method onProgressUpdate, as it has been implemented to run on the UI thread.
Now, each time you want to show the progress from doInBackground, call it by passing an argument. To be clear, AsyncTask (String, Integer, String) uses argument types:
First is the type of argument you pass when you call execute
Second is the type of the argument you pass to onProgressUpdate
Third is the type of argument you pass to onPostExecute
I'm not sure if I understood what is your problem, but it seems to me, that you cannot interact with UI because the ProgressDialog is not cancelable, and it's in front of everything else.
You will only have feedback when dialog is dismissed.
In the OnResume method of my fragmentActivity i try to:
Check if an internet connection is available, if not display a FragmentDialog
if the var storeId id is set to 0, call a new activity whose ask for the id
display the activity
Here is my code:
#Override
protected void onResume() {
super.onResume();
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager.getActiveNetworkInfo() ==null){
noConDialog.show(getFragmentManager(), NET_ALERT_DIALOG);
Log.e("jedois","pas m'afficher");
}
if (storeId == 0) { //si on a plus la boutique id
//call logon activity
Intent logonActivity = new Intent(ShoppingActivity.this, LogonStoreActivity.class);
startActivityForResult(logonActivity, LOGON_STORE_REQUEST);
}
}
The problem is, after execute the lines "noConDialog.show(getFra..."the dialog appear but on resume execute the other line to, the my second activity start and hide my dialog.
A dialog is modal, then the app must wait the end of the Dialog, before execute the other lines . Right?
Thanks for your help
Return from the method after calling the dialog.show().
The code will not terminate unless you use return command. there are two ways you can handle this
Method 1 return after showing the diaog.
#Override
protected void onResume() {
super.onResume();
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager.getActiveNetworkInfo() ==null){
noConDialog.show(getFragmentManager(), NET_ALERT_DIALOG);
Log.e("jedois","pas m'afficher");
return;
}
if (storeId == 0) { //si on a plus la boutique id
//call logon activity
Intent logonActivity = new Intent(ShoppingActivity.this, LogonStoreActivity.class);
startActivityForResult(logonActivity, LOGON_STORE_REQUEST);
}
}
Method 2 Move rest of the code into else part, so only one block could execute at a time.
#Override
protected void onResume() {
super.onResume();
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager.getActiveNetworkInfo() ==null){
noConDialog.show(getFragmentManager(), NET_ALERT_DIALOG);
Log.e("jedois","pas m'afficher");
}
else{
if (storeId == 0) { //si on a plus la boutique id
//call logon activity
Intent logonActivity = new Intent(ShoppingActivity.this, LogonStoreActivity.class);
startActivityForResult(logonActivity, LOGON_STORE_REQUEST);
}
}
}
I have created a Login activity which uses another class - LoginService which is an AsyncTask for the network communication.
public void onClick(View view) {
if (editTextPassword.getText().toString() != null & editTextUsername.getText().toString() != null){
new LoginService(editTextUsername.getText().toString(), editTextPassword.getText().toString()).execute();
if(loginSuccess!=false){
//Used to move to the Cases Activity
Intent casesActivity = new Intent(getApplicationContext(), CasesActivity.class);
startActivity(casesActivity);
}else{
Toast.makeText(getApplicationContext(),"Incorrect Details", Toast.LENGTH_LONG).show();
}
}
else{
//Display Toaster for error
Toast.makeText(getApplicationContext(),"Please enter your details", Toast.LENGTH_LONG).show();
}
}
Before the LoginService has finished executing, the activity has already moved to another activity via the Intent variable. I do not understand why. The idea of the LoginService is to validate the credentials of the user. If it returns true, then it can switch to the other activity.
You do not want to do this in this way. The .execute() will begin as soon as possible, but there is no guarantee (and perhaps guaranteed not to) that it will get your loginSuccess value back to you in time.
Everything after new LoginService(...).execute(); should be moved into onPostExecute():
private Context mContext = null;
public void setContext(Context context) {
mContext = context;
}
#Override
protected void onPostExecute(Void result) {
if(loginSuccess!=false){
//Used to move to the Cases Activity
Intent casesActivity = new Intent(mContext, CasesActivity.class);
startActivity(casesActivity);
}else{
Toast.makeText(mContext,"Incorrect Details", Toast.LENGTH_LONG).show();
}
}
Then, you have to call setContext() like so:
LoginService service = new LoginService(editTextUsername.getText().toString(), editTextPassword.getText().toString());
service.setContext(getApplicationContext());
service.execute();
You should move
Intent casesActivity = new Intent(getApplicationContext(), CasesActivity.class);
startActivity(casesActivity);
}else{
Toast.makeText(getApplicationContext(),"Incorrect Details", Toast.LENGTH_LONG).show();
}
into LoginService's onPostExecute.
In this way you are sure the asynctask has finished its work.
In any case it's quite strange the other activity gets started, it might be because of an old assignement of loginSuccess to true
How to return the result from the asynctask?
Catch the result of AsyncTask from onPostExecute().
#Override
public void onPostExecute(Boolean result)
{
boolean loginSuccess = result;
if(loginSuccess!=false) {
Intent casesActivity = new Intent(getApplicationContext(), CasesActivity.class);
startActivity(casesActivity);
}
else {
Toast.makeText(getApplicationContext(),"Incorrect Details", Toast.LENGTH_LONG).show();
}
}
The data type of result in AsyncTask depends on the 3rd Type parameter.
Sometimes we think execute() method of AsyncTask will return a result which is wrong. It will return an AsyncTask itself
I am using AsyncTask like this
public class AccountReportActivity extends Activity {
private OrgaLevelTask orgaLevelTask;
public void onCreate(Bundle savedInstanceState) {
......
orgaLevelTask = new OrgaLevelTask(AccountReportActivity.this, spinner_orgaLevel, spinner_branch, txt_extra, txt_extra1);
orgaLevelTask.execute();
} //end of onCreate
} //end of class AccountReportActivity
task:
public class OrgaLevelTask extends AsyncTask<Void, Void, ArrayList<OrgaLevel>> {
//Constrcutor
public OrgaLevelTask(AccountReportActivity accountReportActivity, Spinner spinner_orgaLevel, Spinner spinner_branch, TextView txt_extra, TextView txt_extra1) {
this.accountReportActivity = accountReportActivity;
this.spinner_orgaLevel = spinner_orgaLevel;
....
} //end of constructor
#Override
protected ArrayList<OrgaLevel> doInBackground(Void... arg0) {
return callWebService();
} //end of doInBackground()
private ArrayList<OrgaLevel> callWebService() {
try {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
......
} catch (SocketTimeoutException e) {
Toast.makeText(accountReportActivity, "Service is not connected, Please make sure your server is running", Toast.LENGTH_LONG).show();
return null;
} catch(Exception e) {
e.printStackTrace();
System.out.println();
}
} //end of callWebService()
} //end of class OrgaLevelTask
My this task call another AsyncTask which has the same code. The problem is if server is running then everything fine. But if server is not running and i call the web service then i get the exception that Force Application close. Why? I am handling SocketTimeoutException IF exception happens then i am saying that show toast on my Activity but why it is force closing the application. How can i handle it? Thanks
You can check the internet connection this way first
public static boolean checkConnection(Context context) {
final ConnectivityManager mConnectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo netInfo = mConnectivityManager.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
} else
return false;
}
In this method
// Checking the internet connection
if (!InternetConnectionCheck.checkConnection(this)) {
Utilities.alertDialogBox(this, R.string.Title_String,
R.string.No_Internet_connection_String);
} else {
orgaLevelTask = new OrgaLevelTask(AccountReportActivity.this, spinner_orgaLevel, spinner_branch, txt_extra, txt_extra1);
orgaLevelTask.execute();
}
you should not use use Toast in doInBackground
catch (SocketTimeoutException e) {
Toast.makeText(accountReportActivity, "Service is not connected, Please make sure your server is running", Toast.LENGTH_LONG).show(); //<----------------------