I'm trying to show an AlertDialog in my AsyncTask on onCancelled. My task is stopping properly, but the dialog isn't appearing. Here's my code below... Need help. Thanks...
public class getWebPage extends AsyncTask<String, Integer, String> {
protected void onPreExecute(String f) {
// TODO Setting up variables
f = "f";
}
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
Looper.prepare();
DefaultHttpClient urlClient = new DefaultHttpClient();
HttpGet getHtml = new HttpGet(PAGE_URL);
ResponseHandler<String> resHandler = new BasicResponseHandler();
try {
String htmlPage = urlClient.execute(getHtml, resHandler);
Log.d("Html Page", htmlPage);
confessionsPage = new File(getApplicationContext().getFilesDir(), "ConfessionsPage.html");
if (!confessionsPage.exists()) {
confessionsPage.createNewFile();
}
writer = new PrintWriter(confessionsPage, "UTF-8");
writer.print(htmlPage.replace("<!--", "").replace("-->", ""));
writer.flush();
writer.close();
Document doc = Jsoup.parse(confessionsPage, "UTF-8", "http://www.facebook.com/");
if (doc.title().contains("Welcome to Facebook")) {
aDialog = new AlertDialog.Builder(OpeningActivity.this).create();
aDialog.setTitle("Restricted Access");
aDialog.setMessage("Looks like your Confessions Page only allows login access. You may be logged in right now, but the app" +
" can't. Tell your page admin to allow non-logged in access for your confessions page.");
aDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
aDialog.dismiss();
}
});
getWebPage.this.cancel(true);
}
and here is my on cancelled method:
#Override
protected void onCancelled() {
// TODO Auto-generated method stub
super.onCancelled();
aDialog.show();
}
Try move everything from the doInBackground to the onCancelled.
So this will be your onCancelled:
AlertDialog aDialog = new AlertDialog.Builder(OpeningActivity.this).create();
aDialog.setTitle("Restricted Access");
aDialog.setMessage("Looks like your Confessions Page only allows login access. You may be logged in right now, but the app" +
" can't. Tell your page admin to allow non-logged in access for your confessions page.");
aDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
aDialog.dismiss();
}
});
aDialog.show();
And remove everything from the doInBackground.
Alternatively you can put this into your AsyncTask's onPostExecute too and change the result type of the task to Boolean. in the onPostExecute check the result. If it's false and you need to display this error. display it from there.
Note that onPostExecute is executed by the UI thread so you don't need the runOnUiThread stuff.
Related
I am trying to use a AlertDialog in Android which will notify the users that they are runing in offline mode after checking the internet connection.
I have used the following codes:
protected Void doInBackground(Void... params) {
if (this.isOnline()) {
new GetJson().execute();
} else {
AlertDialog.Builder builder1 = new AlertDialog.Builder(homeFragment);
builder1.setMessage("INTERNET CONNECTION NOT AVAILABLE. Now you are viewing the news in Offline Mode.");
builder1.setCancelable(true);
AlertDialog alert1 = builder1.create();
alert1.show();
try {
saveFile = new SaveIntoFile(fileName);
jsonStr = saveFile.read();
// Log.d(TAG,"offline data reading from a file");
if (!jsonStr.equals(null))
new GetDatas().execute();
else {
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
But I am getting the error on adding the codes for AlertDialog. The app works fine without the codes for AlertDialog.
What can be the mistakes with this code and how can i correct it to work well??
doInBackground() runs on a separate thread, other than the main thread. You can use UI elements only on main thread. Try using runOnUiThread() method inside doInBackground() to show the dialog.
here AlertDialog will not work, you can use
System.out.println("some text");
if you are using alert just for testing purpose.
otherwise you have to set into a parameter and what ever text you want to put in alertbox and just use it in main thread.
if you have any confusion please let me know .
In Android you can do UI operations only in main thread. So you can show dialog in onPostExecute method. Example:
class anyClassName extends AsyncTask<String,String,String>{
/* uses worker thread */
protected String doInBackground(Void... params) {
if (this.isOnline()) {
new GetJson().execute();
} else { return null }
// ... rest of your code
return ""
}
/* uses main thread*/
protected void onPostExecute(String result){
if(result == null ){
AlertDialog.Builder builder1 = new AlertDialog.Builder(homeFragment);
builder1.setMessage("INTERNET CONNECTION NOT AVAILABLE. Now you are viewing the news in Offline Mode.");
builder1.setCancelable(true);
AlertDialog alert1 = builder1.create();
alert1.show();
}
}
}
class myAsync extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
if(yourWorkIsDone){
return new String("done");
}else{
return new String("Error message");
}
//BUT, if you'd like to check and update user on the error and keep trying then this way
// use just one of these two examples
if(yourWorkIsDone){
// definately is done but hey it depends on you
publishProgress(new String("done"));
}else{
// this is when you have error and wona let the user know about and keep trying to hit it right
publishProgress(new String("error message"));
}
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
// here your task is done
// you can put myAlertDialogToShow(Context context,String message) depending on ur choice
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
// here your task is running but you are just informing user, runs on the ui..
// you can put myAlertDialogToShow(Context context,String message) depending on ur choice
}
}
void myAlertDialogToShow(Context context,String message){
AlertDialog.Builder builder1 = new AlertDialog.Builder(context);
builder1.setMessage(message);
builder1.setCancelable(true);
AlertDialog alert1 = builder1.create();
alert1.show();
}
ayt..check for silly errors and spellings.. im tired
I am loading a certain Url into a WebView . This is a login page and the user gets authenticated. When Authenticated he is shown a certain page. At this point I want to stop the Webview loading and start a new activity.
To do this, Iam catching the redirected url and comparing it with a String with my values if it matches then I stop the page loading. But the String Iam trying to compare with the url occurs twice. First when the page starts loading and second when the page complately finishes loading.I want to compare to the second one
But this does not start the new activity.
This is what I have tried:-
myWebView.loadUrl(url);
final ProgressDialog progressBar = ProgressDialog.show(Details1.this, "Loading..", "Please wait!");
myWebView.setWebViewClient(new WebViewClient()
{
private Object progress;
#Override
public void onPageFinished(WebView view, String url)
{
// TODO Auto-generated method stub
super.onPageFinished(view, url);
if(progressBar!=null && progressBar.isShowing())
{
progressBar.dismiss();
}
url= view.getUrl();
redirected= Uri.decode(url);
/*AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
Details1.this);
// set title
alertDialogBuilder.setTitle("Your Title");
// set dialog message
alertDialogBuilder
.setMessage(redirected)
.setCancelable(false)
.setNegativeButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();*/
if(redirected!=null && redirected.contains(endpointHost+"/AuthorizeDevice/index/"+deviceId))
{
Utility.ProgressDialogFragment progDialog = new Utility.ProgressDialogFragment();
progDialog.show(getFragmentManager(), "Wait");
myWebView.stopLoading();
String authorizationContentString = AuthenticateDeviceEndPoint+ "?encodedAccountName=" + encodedAccountName + "&deviceId=" + deviceId + "&hostUrl=" + hostUrl;
authorizationContentString =authorizationContentString.replace("|", "%7C");
//UserInformation userInfo;
JSONParser parser = new JSONParser();
Object register;
try
{
//userInfo
// String responseData= new AuthenticateDevice(Details1.this,myprogressDialog).execute(authorizationContentString).get();
String responseData = new AuthenticateDevice(Details1.this, progDialog).execute(authorizationContentString).get();
register = parser.parse(responseData);
org.json.simple.JSONObject authDevice = (org.json.simple.JSONObject) register;
//Convert Json objects to strings
usersname = (String) authDevice.get("FirstName");
AuthenticationInformation authInfo = new AuthenticationInformation(Details1.this);
authInfo.SetUserInformation(username );
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (ExecutionException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Intent myIntent = new Intent(Details1.this, Home.class);
myIntent.putExtra("UsersName", usersname);
myIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(myIntent);
finish();
}
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
// TODO Auto-generated method stub
view.loadUrl(url);
return true;
}
I want to implement a sign up activity where user insert his/her information then click a button to send this information to web service which stored this information in a database.
I put the code for connecting to web service in a separated Thread (Not in UI Thread), and I want to display a progressdialog until the connection to web service finish, then I want to display an AlertDialog to display different messages like(this email is used try different one , or Sign up successes!)
here is the which excuse when user click sign up button :
public void SignupNewUser (View V)
{
Working = ProgressDialog.show(this, "Working..", "Connecting To Server");
Runnable work = new Runnable() {
#Override
public void run() {
Edit_Text_FName = (EditText) findViewById(R.id.Edit_Text_Fname_Signup);
Edit_Text_LName = (EditText) findViewById(R.id.Edit_Text_Lname_Signup);
Edit_Text_Password = (EditText) findViewById(R.id.Edit_Text_Password_Signup);
Edit_Text_Email = (EditText) findViewById(R.id.Edit_Text_Email_Signup);
S1 = (Spinner) findViewById(R.id.Spinner_Signup);
SignupPerson SUPerson = new SignupPerson();
SUPerson.F_Name = Edit_Text_FName.getText().toString().trim();
SUPerson.L_Name = Edit_Text_LName.getText().toString().trim();
SUPerson.E_Mail = Edit_Text_Email.getText().toString().trim();
SUPerson.PassW = Edit_Text_Password.getText().toString().trim();
SUPerson.Gen = Choosen_Gender;
SUPerson.Cou_Id = S1.getSelectedItemPosition();
METHOD = "signup";
SoapObject Request = new SoapObject(NAMESPACE, METHOD);
PropertyInfo P = new PropertyInfo();
P.setName("SUPerson");
P.setValue(SUPerson);
P.setType(SUPerson.getClass());
Request.addProperty(P);
SoapSerializationEnvelope envolope = new SoapSerializationEnvelope(SoapSerializationEnvelope.VER11);
envolope.dotNet = true;
envolope.setOutputSoapObject(Request);
envolope.addMapping(NAMESPACE, "SignupPerson", new SignupPerson().getClass());
HttpTransportSE ahttp = new HttpTransportSE(URL);
SoapPrimitive Res = null;
try
{
ahttp.call(NAMESPACE+METHOD, envolope);
Res = (SoapPrimitive) envolope.getResponse();
}
catch (Exception ex)
{
//ex.printStackTrace();
result = -1;
}
if (result != -1)
{
result = Integer.parseInt(Res.toString());
}
Working.dismiss();
}
};
Thread SS = new Thread(work);
SS.start();
switch (result)
{
case -1:
showDialog(-1);
break;
case 0:
showDialog(0);
break;
case 1:
showDialog(1);
break;
case 2:
showDialog(2);
break;
default:break;
}
}
#Override
protected Dialog onCreateDialog(int id)
{
switch (id)
{
case -1:
return new AlertDialog.Builder(this)
.setTitle("error!")
.setMessage("error connecting to the server. please try again")
.setIcon(R.drawable.ic_error)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
}
})
.create();
case 0:
return new AlertDialog.Builder(this)
.setTitle("error!")
.setMessage("You have entered an Exists Email, Please try another one")
.setIcon(R.drawable.ic_error)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
}
}).create();
case 1:
return new AlertDialog.Builder(this)
.setTitle("error!")
.setMessage("Server Error, Please Try Again Later")
.setIcon(R.drawable.ic_error)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
}
})
.create();
case 2:
return new AlertDialog.Builder(this)
.setTitle("Registration successfully!")
.setMessage("Click OK to Sign in and Start Usign Hello!!")
.setIcon(R.drawable.ic_success)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
Intent i = new Intent(SignupActivity.this ,MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
})
.create();
}
return null;
}
here , SUPerson is an object which hold user information, and result is an integer which indicate which AlertDialog will display after connection to web service end.
my question is that when I run the above code ,, No Alert Dialog message appear !
why ?
If you use an AsyncTask you will have a much easier time doing this. I think you might not be getting your dialog because you're trying to show it immediately after starting the thread.
With the AsyncTask, you can have your server connection running in doInBackground() on a separate thread and then you can have your dialog called in onPostExecute().
Let me know if that makes sense! The link is pretty clear on how to use it. :)
Edit: I also wanted to mention, if you use the AsyncTask, it allows you to easily set up a ProgressDialog in the onProgressUpdate() method.
For some reason my call to AsyncTask.cancel only works once, i.e. for the first instance of the task, and never again. The first task cancels beautifully and hits the onCancelled method. All the others seem to ignore the cancel() call and end up in onPostExecute.
The task is executed from a service:
public class ZitFtpService extends Service implements ZitFtpServiceInterface
{
//Blah blah
public void connect(String server, int port)
{
if(!isConnecting){
isConnecting = true;
ConnectTask task = new ConnectTask();
task.execute(server, String.valueOf(port));
}
}
//Blah blah blah
As you can see it is a new instance every time. I can't see why the first one would behave differently from the subsequent ones. The AsyncTask is a private inner class:
private class ConnectTask extends AsyncTask<String, String, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
boolean result = false;
try {
publishProgress(
"start", "Connecting to "+ params[0] + ":" + params[1]);
Log.v("ZIT", params[0] + " " + params[1] + " " + params.length);
conn.connect(params[0], Integer.valueOf(params[1]), 1000);
result = true;
} catch (NumberFormatException e) {
Log.e("ZIT", e.getMessage());
} catch (IOException e) {
failMessage = e.getMessage();
e.printStackTrace();
}
return Boolean.valueOf(result);
}
private void cancelConnect() {
try {
conn.disconnect();
} catch (IOException e) {
e.printStackTrace();
} finally {
conn = new ZMobileFTPImpl();
}
if(!(dialog==null)) {
dialog.dismiss();
}
}
#Override
protected void onCancelled() {
Log.v("ZIT", "I was cancelled.");
isConnecting = false;
}
#Override
protected void onProgressUpdate(String... values) {
if(dialog == null) {
dialog = new ProgressDialog(progressActivity);
dialog.setCancelable(true);
dialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
ConnectTask.this.cancel(true);
cancelConnect();
dialog.dismiss();
}
});
dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
}
dialog.setMessage(values[1]);
dialog.setCancelable(true);
dialog.show();
}
#Override
protected void onPostExecute(Boolean result) {
dialog.dismiss();
if(!result) {
AlertDialog.Builder builder =
new AlertDialog.Builder(progressActivity);
builder.setMessage(failMessage).setTitle("Error");
failMessage = "";
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog failDialog = builder.create();
failDialog.show();
}
isConnecting = false;
}
}
From Doc's
There are a few threading rules that must be followed for this class to work properly:
The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN.
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
So, you can call an AsyncTask multiple times by creating new instance every time like
new ConnectTask().execute(params);
This is intentional as you can only execute an AsyncTask instance once, you can run task.execute multiple times though...
Anyhow, I believe you forgot to add the super.onCancelled in following override:
#Override
public void onCancelled() {
//...
super.onCancelled();
}
Try if that helped, and otherwise you should share the error or log so we can troubleshoot that :)
I want to create a dialogBuilder with a text field and a button on it. The idea is to make the program wait for any further actions until the text in the field is entered and the OK button is clicked. Below is the code:
private static final Object wait = new int[0];
private static String result = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Handler h = new Handler();
final Context context = MainActivity.this;
h.post(new Runnable() {
public void run() {
final Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setTitle(R.string.app_name);
final LinearLayout panel = new LinearLayout(context);
panel.setOrientation(LinearLayout.VERTICAL);
final TextView label = new TextView(context);
label.setId(1);
label.setText(R.string.app_name);
panel.addView(label);
final EditText input = new EditText(context);
input.setId(2);
input.setSingleLine();
input.setInputType(InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_VARIATION_URI
| InputType.TYPE_TEXT_VARIATION_PHONETIC);
final ScrollView view = new ScrollView(context);
panel.addView(input);
view.addView(panel);
dialogBuilder
.setCancelable(true)
.setPositiveButton(R.string.app_name,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
result = input.getText().toString();
synchronized (wait) {
wait.notifyAll();
}
dialog.dismiss();
}
}).setView(view);
dialogBuilder.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface arg0) {
result = null;
synchronized (wait) {
wait.notifyAll();
}
}
});
dialogBuilder.create().show();
}
});
String localResult = null;
try {
synchronized (wait) {
Log.d("Waiting", "Waiting " + localResult);
wait.wait();
}
localResult = result;
result = null;
if (localResult == null) {
// user is requesting cancel
throw new RuntimeException("Cancelled by user");
}
Log.d("RESULT ", "RESULT " + localResult);
} catch (InterruptedException e) {
localResult = result;
result = null;
if (localResult == null) {
// user is requesting cancel
Log.d("CANCELED ", "CANCELED " + localResult);
throw new RuntimeException("Cancelled by user");
}
}
Log.d("RESULT AFTER THE DIALOG", "RESULT AFTER THE DIALOG " + result);
}
The program is going to Log.d("Waiting", "Waiting " + localResult); and after that just waiting. NO DIALOG BUILDER IS SHOWN on the activity window. I used the debug mode and saw that the program flow is not entering the run() method, but the value of the Handler.post() is true. And for this reason the dialog is not shown, and the program is waiting.
I have tried to remove the moment with waiting (remove the Handler.post()), just to see if the dialog will show, and it showed and all moved well, but the result was not I am needing - I want the program to wait the input from the dialog ... I am really out of ideas.
Would you please give me some suggestions as I am really out of ideas.
Thanks a lot!
Handlers don't run in a separate thread. So when you call wait() :
synchronized (wait) {
Log.d("Waiting", "Waiting " + localResult);
wait.wait();
}
It waits indefinitely since the handler runs on the same thread as the current thread. Your Runnable can only be executed after the onCreate() method finishes but this will never happen because you just called wait().
You should reconsider your idea and find a workaround (for example, show the dialog the usual way and disable the "OK" button as long as the user does not enter a valid text). But calling wait() on the UI thread cannot go well.
You should be running the display of the Dialog in the UI Thread, not a seperate thread.
An example would be something like this:
In the onCreate()
runOnUiThread(new Runnable() {
#Override
public void run() {
// Display progress dialog when loading contacts
dialog = new ProgressDialog(this);
// continue with config of Dialog
}
});
// Execute the Asynchronus Task
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
// code to execute in background
return null;
}
#Override
protected void onPostExecute(Void result) {
// Dismiss the dialog after inBackground is done
if (dialog != null)
dialog.dismiss();
super.onPostExecute(result);
}
}.execute((Void[]) null);
Specifically what is happening here is the Dialog is being displayed on the UI thread and then the AsyncTask is executing in the background while the Dialog is running. Then at the end of the execution we dismiss the dialog.