I created this AsyncTask inner class and now I want to make it outer. Here is the code:
private class DownloadDataFromServer extends AsyncTask<String, Integer, String> {
ProgressDialog dialog;
boolean connErr = false;
boolean soErr = false;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(HomePage.this); !!!!PROBLEM!!!!
dialog.setIndeterminate(false);
dialog.setMax(100);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setCancelable(false);
dialog.setTitle("Download");
dialog.setMessage("Updating...");
dialog.show();
super.onPreExecute();
}
#Override
protected String doInBackground(String... urls) {
// do something
}
protected void onProgressUpdate(Integer... progress) {
// Update the progress
dialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
if (connErr || soErr) {
String msg = "Bad connection";
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(HomePage.this); !!!!PROBLEM!!!!
builder.setCancelable(false);
builder.setTitle("Connection timeout");
builder.setMessage(msg);
builder.setPositiveButton("Retry", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
new DownloadDataFromServer().execute(new String[] { "http://www.example.com" });
}
});
builder.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish(); !!!!PROBLEM!!!!
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
if (Integer.parseInt(result) <= 0) {
Toast.makeText(getBaseContext(), "Error!", Toast.LENGTH_SHORT).show(); !!!!PROBLEM!!!!
} else {
Toast.makeText(getBaseContext(), "OK!", Toast.LENGTH_SHORT).show(); !!!!PROBLEM!!!!
}
}
dialog.dismiss();
}
}
Please note "!!!!PROBLEM!!!!" strings in the above code: there are all the errors that I get. I tried to apply some workarounds but finally I could not make it working. In addition I also have to use
private Database db = new Database(this);
but I do not know what to put in place of "this". Please help me to convert this inner class in the right way.
You should make one argument constructor to DownloadDataFromServer class and pass Context as argument like
Context mCon;
public DownloadDataFromServer(Context con){
this.mCon=con;
}
and used this mCon context to anywhere in your DownloadDataFromServer like so
builder = new AlertDialog.Builder(mCon);
and at last called DownloadDataFromServer from any Activity like
new DownloadDataFromServer(your_Activity.this).execute(......);
Make yout DownloadDataFromServer have a constructor accepting HomeScreen, save the home screen in a field in the constructor and then use that field everywhere instead of HomeScreen.this.
You may have to make some of your private fields of HomeScreen public (or provide accessors) because of that.
You do not want to do all that though, what's the advantage?
Related
I'm scanning QR code using Google's Vision. I got help from this link. I want to show AlertDialog after getting the value from QR code. If I directly show alertdialog inside receiveDetections() method I'm getting "Can't create looper" error. So I called the alertdialog inside runOnUiThread(). But now I'm unable to dismiss the dialog. Would like to know what's the reason for this.
#Override
public void receiveDetections(Detector.Detections<Barcode> detections){
final SparseArray<Barcode> barcodes = detections.getDetectedItems();
if (barcodes.size() != 0) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
String val = barcodes.valueAt(0).displayValue;
showAlert(val);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void showAlert(String val){
try {
if (!val.equals("")) {
AlertDialog.Builder builder = new AlertDialog.Builder(ScannedBarcodeActivity.this);
builder.setTitle(emp.getName())
.setPositiveButton(newStatus, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
emp.setStatus(newStatus);
viewModel.updateEmployee(emp);
dialog.dismiss();
}
})
.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
}catch (Exception e){
e.printStackTrace();
}
}
Even though now the alertdialog is showing, when I click CANCEL button, the alert does not gets dismissed.
I think receiveDetections is being called more than once, which is resulting in multiple instances of AlertDialog. So when you press CANCEL button you might be cancelling only one of those multiple opened dialogs.
You can add logs to see how many times receiveDetections is being called, or just hit CANCEL button multiple times and all the previously opened alerts will be cancelled
*Possible Reason:
receiveDetections will be executed every-time your camera passes image to QRScanner,
and as your camera is continuously streaming images, QRScanner is calling receiveDetections again and again.
The reason why you alert dialog is not dismissing because you are new object of AlertDialog each time when receiveDetections called and in your case receiveDetections multiple time.
You have to create a Singleton class object:
public class singleTonDialogExample {
static TextToSpeech t1;
private static singleTonExample ourInstance = new singleTonDialogExample();
private Context appContext;
private ICallBack iCallBack;
public interface ICallBack{
void onYesPressed();
void onNoPressed();
}
private singleTonDialogExample() { }
public static Context get() {
return getInstance().getContext();
}
public static synchronized singleTonDialogExample getInstance() {
return ourInstance;
}
public void init(Context context) {
if (appContext = = null) {
this.appContext = context;
}
}
private Context getContext() {
return appContext;
}
public void setICallBack(ICallBack callBack){
this.iCallBack=callBack;
}
public void AlertDialog(final MainActivity mainActivity,String title,String message) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mainActivity);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton("yes",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
iCallBack.onYesPressed();
}
});
alertDialogBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
iCallBack.onNoPressed();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
Create the Dialog in Activity like this:
singleTonDialogExample dialog;
dialog = singleTonExample.getInstance();
dialog.init(getApplicationContext());
dialog.setICallBack(this);
dialog.AlertDialog(MainActivity.this,"Title","This is message");
Also implement the ICallBack interface in your activity or fragment.
I have a fully functional asynctask in my android app, but when I'm not connected it causes my app to crash in the Error message within my Activity (in AlertDialog.Builder) stemming from the Async not connecting. I pass Context to my async, so that may have something to do with it, but not sure.
Below is the code from Async class and Activity. LogCat is telling me error is occurring in the AlertDialog alert builder.create(). How can I solve?
From Async class:
InputsRecapUploadTask extends AsyncTask<String, Void, Integer> {
public InputsRecapUploadTask(InputsRecap activity,
ProgressDialog progressDialog, Context ctx) {
this.activity = activity;
this.myCtx = ctx;
this.progressDialog = progressDialog;
}
#Override
protected void onPreExecute() {
progressDialog.show();
}
}
#Override
protected Integer doInBackground(String... arg0) {
//// http code
responseCode = 1;
}
}
} catch (Exception e) {
e.printStackTrace();
progressDialog.dismiss();
activity.showLoginError("");
}
return responseCode;
}
#Override
protected void onPostExecute(Integer headerCode) {
progressDialog.dismiss();
if (headerCode == 1)
activity.login(id);
else
activity.showLoginError("");
}
Activity Class:
public void showLoginError(String result) {
AlertDialog.Builder builder = new AlertDialog.Builder(InputsRecap.this);
builder.setPositiveButton("okay",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.setMessage("unable to upload database");
AlertDialog alert = builder.create();
alert.setCancelable(true);
alert.show();
}
If an exception is thrown in your doInBackground method these two lines:
progressDialog.dismiss();
activity.showLoginError("");
Will cause Exception - you can not modify the UI from within the doInBackground method. Instead set a flag and show the error dialog in the onPostExecute which is executed in the main thread.
Check the link below especially the topic under heading The 4 steps.
http://developer.android.com/reference/android/os/AsyncTask.html
I'm using a AsyncTask
I use parent to create the intent no errors.
The line to creat a dialog gives a
parent cannot be resolved to a ye.
new parent.AlertDialog.Builder(this)
The error I get is that parent does not exist, but I use parent in the same methed to call the intent
code block
private class SendTextOperation extends AsyncTask {
#Override
protected void onPreExecute() {
//Update UI here
}
#Override
protected String doInBackground(String... params) {
// Talk to server here to avoid Ui hanging
rt=TalkToServer("http://besttechsolutions.biz/projects/bookclub/login.php");
return(rt);
}
#Override
protected void onPostExecute(String result) {
if (rt.contains("ok"))
{
Intent i = new Intent(parent, cChat.class);
startActivity(i);
}
else
{
new parent.AlertDialog.Builder(this)
.setTitle("Game Over")
.setMessage("Your time is up, You saved "
+" Million more people!!")
.setNeutralButton("Try Again",new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dlg, int i)
{
}} ).show();
}
}
}
For showing AlertDialog from non Activity you will need to pass Current Activity Context to non Activity class in your case to SendTextOperation class.
Create an Constructor for SendTextOperation as :
public class SendTextOperation extends AsyncTask<String,Void,String>{
Context context;
public SendTextOperation(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
//Update UI here
}
#Override
protected String doInBackground(String... params) {
// Talk to server here to avoid Ui hanging
rt=TalkToServer("http://besttechsolutions.biz/projects/bookclub/login.php");
return(rt);
}
#Override
protected void onPostExecute(String result) {
if (rt.contains("ok"))
{
Intent i = new Intent(context, cChat.class);
startActivity(i);
}
else
{
new context.AlertDialog.Builder(context)
.setTitle("Game Over")
.setMessage("Your time is up, You saved "
+" Million more people!!")
.setNeutralButton("Try Again",new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dlg, int i)
{
}} ).show();
}
}
}
and start SendTextOperation AsyncTask as :
SendTextOperation sendtxtasyncTask = new SendTextOperation(CurrentActivity.this);
sendtxtasyncTask.execute("");
Lets say you have that class declared inside a class named MyActivity
Then use instead of this, MyActivity.this when creating the Dialog.
It looks like you should be calling it like this:
final AlertDialog.Builder builder = new AlertDialog.Builder(_context);
builder.setMessage(_context.getString(R.string.error) + ": " + _errorMessage)
.setTitle(_context.getString(R.string.loginError))
.setIcon(android.R.drawable.ic_dialog_alert)
.setCancelable(true)
.setPositiveButton(_context.getString(R.string.ok), null);
final AlertDialog alert = builder.create();
alert.show();
(My own sample code)
It looks like your error is trying to do parent.AlertDialog.Builder(this), where you need to use new AlertDialog.Builder(parent), if parent is your context.
I display an Alertbox with ok or cancel.
I want to implement an asynch task on the press of OK. Havent done asynch and been struggling with it for awhile. I dont understand where the asych class goes also. Does it go outside the method that is being executed or outside of it? Current code as follows:
private abstract class DoAsynchTask extends AsyncTask<Void,Void,Void>
{
protected void doInBackground()
{
Drawable drawable= getImage(imageSelect);
MakeWallPaper(drawable,1);
}
/* protected void onProgressUpdate(Integer... progress)
{
setProgress(progress[0]);
}*/
protected void onPostExecute()
{
Toast.makeText(getApplicationContext(), "Wallpaper Saved.",Toast.LENGTH_LONG).show();
AlertDialogProcessing=0;
}
}
public void getWallpaper(final View v)
{
if(AlertDialogProcessing==0)
{
final String title="Set Image to Wallpaper";
final String message="Press OK to set as Wallpaper or CANCEL.\nWait after pushing OK.";
final String ok="OK";
final String cancel="CANCEL";
final AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
alertbox.setCancelable(true);
alertbox.setIcon(android.R.drawable.ic_dialog_alert);
alertbox.setTitle(title);
alertbox.setMessage(message);
alertbox.setNegativeButton(cancel, null);
final AlertDialog dlg = alertbox.create();
alertbox.setPositiveButton(ok,new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dlg, int which)
{
DoAsynchTask.execute(null,null,null); //<<<<Wrong
dlg.dismiss();
Vibrate(ClickVibrate);
}
});
alertbox.setNegativeButton(cancel,new DialogInterface.OnClickListener(){ public void onClick(DialogInterface arg0, int arg1){AlertDialogProcessing=0;
Vibrate(ClickVibrate); } });
alertbox.show();
}
}
There's a couple problems in the code.
1) First of all, the compiler is probably giving you this message:
The type MyActivity.DoAsynchTask must implement the inherited abstract
method
AsyncTask.doInBackground(Void...) MyActivity.java
If you look closely at the error message, you'll realize that what you defined was this:
protected void doInBackground() {
which is not what is needed. Even though it might seem silly, when your AsyncTask subclass takes Void as the generic parameter types, that means that doInBackground() must look like this:
protected Void doInBackground(Void... arg0) {
The compiler complains because you haven't implemented that (exact) method. When you inherit from an abstract class, and fail to implement all of its required/abstract method(s), then you can only get it to compile by marking the subclass as abstract, too. But, that's not really what you want.
So, just change your code to (remove abstract from your class):
private class DoAsynchTask extends AsyncTask<Void,Void,Void>
and
protected Void doInBackground(Void... arg0) {
{
Drawable drawable= getImage(imageSelect);
MakeWallPaper(drawable,1);
return null;
}
2) And the second problem, as others have pointed out, is that you must start your task with:
new DoAsynchTask().execute();
not
DoAsynchTask.execute(null,null,null);
Your code would only be correct if execute() was a static method in AsyncTask, which it's not. In order to invoke the non-static execute() method, you first need a new instance of the DoAsynchTask class. Finally, the null, null, null parameter list is also not necessary, although I don't think it will cause the code to fail either.
Since your doInBackground() does not specify any parameters, you should call DoAsynchTask.execute() without parameters.
Why is your class abstract? Normally an AsyncTask should be an inner class of the activity starting it. So create your dialog in the activity, and execute the AsyncTask when clicking on OK button, like you do.
//final working copy -Thanks ALL
public void getWallpaper(final View v)
{
Vibrate(ClickVibrate);
final class SetWallPaperAsynchTask extends AsyncTask<Void,Void,Void>
{
#Override
protected Void doInBackground(Void... arg0)
{
Drawable drawable= getImage(imageSelect);
MakeWallPaper(drawable,1);
return null;
}
#Override
protected void onPostExecute(Void result)
{Toast.makeText(getBaseContext(), "Wallpaper Saved.", Toast.LENGTH_LONG).show();
AlertDialogProcessing=0;
}
}
if(AlertDialogProcessing==0)
{
ProgressDialog progress;
final String title="Set Image to Wallpaper";
final String message="Press OK to set as Wallpaper or CANCEL.";
final String ok="OK";
final String cancel="CANCEL";
final AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
alertbox.setCancelable(true);
alertbox.setIcon(android.R.drawable.ic_dialog_alert);
alertbox.setTitle(title);
alertbox.setMessage(message);
alertbox.setNegativeButton(cancel, null);
final AlertDialog dlg = alertbox.create();
alertbox.setPositiveButton(ok,new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface arg0, int arg1)
{
new SetWallPaperAsynchTask().execute();
dlg.dismiss();
Vibrate(ClickVibrate);
}
});
alertbox.setNegativeButton(cancel,new DialogInterface.OnClickListener(){ public void onClick(DialogInterface arg0, int arg1){AlertDialogProcessing=0; Vibrate(ClickVibrate); } });
alertbox.show();
}
}
I'm a newbie to Android and I'm having some problems with the AsyncTask class. I have a lot of (over 100) check boxes which I want to select or deselect with a "select all" check box.
Unfortunately this takes quite some time, noticeable for the user, so I want to use the ProgressDialog to show that the selecting is in progress.
Now I know that updates of the UI elements are supposed to be done in the UI thread so I have the selecting code in the onProgressUpdate method but the ProgressDialog doesn't show up not until the processing (select or deselecting all checkboxes) is finished...
How is this supposed to be done? Is there any workaround or any other solution? I also tried to go through all the check boxes in the doInBackground() method but I get lots of weird errors (I guess it's because of the UI).
This is my code:
customPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(final Preference preference, final Object object) {
new CbSelection().execute(preference);
return true;
}
});
private class CbSelection extends AsyncTask<Preference, Boolean, Void> {
private ProgressDialog Dialog = new ProgressDialog(Preferences.this);
#Override
protected void onPreExecute() {
Dialog.setMessage("Please wait...");
Dialog.setCanceledOnTouchOutside(true);
Dialog.setCancelable(true);
Dialog.show();
}
#Override
protected Void doInBackground(Preference... pref) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
Preference preference = pref[0];
if(preference.getKey().compareTo("select_all") == 0){
publishProgress(true);
}
return null;
}
#Override
protected void onProgressUpdate(Boolean... ok) {
if(ok[0]== true) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
for(int i = 0; i < screen.getPreferenceCount(); ++i) {
//Dialog.show();
/* select or deselect all checkboxes here... */
}
}
}
#Override
protected void onPostExecute(Void v) {
Dialog.cancel();
}
}
What if you create and show the dialog before executing the AsyncTask? That's the way it usually is used:
private ProgressDialog Dialog;
customPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(final Preference preference, final Object object) {
Dialog = new ProgressDialog(Preferences.this);
Dialog.setMessage("Please wait...");
Dialog.setCanceledOnTouchOutside(true);
Dialog.setCancelable(true);
Dialog.show();
new CbSelection().execute(preference);
return true;
}
});
private class CbSelection extends AsyncTask<Preference, Boolean, Void> {
#Override
protected Void doInBackground(Preference... pref) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
Preference preference = pref[0];
if(preference.getKey().compareTo("select_all") == 0){
publishProgress(true);
}
return null;
}
#Override
protected void onProgressUpdate(Boolean... ok) {
if(ok[0]== true) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
for(int i = 0; i < screen.getPreferenceCount(); ++i) {
/* select or deselect all checkboxes here... */
}
}
}
#Override
protected void onPostExecute(Void v) {
Dialog.dismiss();
}
}