the_gesslar
the_gesslar

Reputation: 387

Trying to get an alert box to popup in response to AsyncTask

I have an app that has a big red voting button on it. Now, I always require that they have a public IP address in order to enable the Vote button.

I learned that I needed to do my fetching of internet things via an AsyncTask, so I made a new class extend it called DetermineIP. This process works, I'm able to get an IP because I have a webpage I built that just provides the IP.

I now am working on handling when they have no connectivity. So, I built an alert box such that it has a Retry button on it. The goal is to allow the user to fix their connectivity issues and then hit Retry until they get their IP.

I cannot seem to add the click handler, I think, because it's being called from the AsyncTask. I get: Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

I full on admit to being a noob and am really just looking to find a way to make this happen.

public void fetchIP()
{
    // UPDATE LABELS
    Resources res = getResources();

    TextView textStatus = (TextView) findViewById(R.id.statusMessage);
    textStatus.setText(res.getString(R.string.status_determining_ip_address));

    enableVoteButton(false);

    String stringURL = res.getString(R.string.ip_url);
    URL urlIP = null;
    try {
        urlIP = new URL(stringURL);
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }

    // start AsyncTask to fetch IP in the background
    getIP = new DetermineIP();
    getIP.setParent(this);
    getIP.execute(urlIP);
    m_working = true;

    // show a dialog box with message that we're determining the IP
    status_dialog = new Dialog(MainActivity.this);
    status_dialog.setCancelable(false);
    status_dialog.setContentView(R.layout.activity_ip);
    TextView textDialogStatus = (TextView) status_dialog.findViewById(R.id.textView);
    textDialogStatus.setText(R.string.status_determining_ip_address);
    status_dialog.show();
}

// If we were able to determine the IP address by fetching from a
// public web server then everything's good. Enable everything, and
// move along from there. Called from DetermineIP.onPostExecute.
public void setIP(String theIP)
{
    m_ip = theIP;

    TextView textStatus = (TextView) findViewById(R.id.statusMessage);
    textStatus.setText(m_ip);
    enableVoteButton(true);
    m_working = false;
    status_dialog.dismiss();
}

// If we were unable to determine an IP address, for whatever reason,
// show a retry alert box, when they hit retry, then start the process
// over again, maybe the user needs to solve a connectivity issue before
// retrying. Called from DetermineIP.onPostExecute.
public void setNoIP()
{
    Resources res = getResources();

    TextView textStatus = (TextView) findViewById(R.id.statusMessage);
    textStatus.setText(res.getString(R.string.status_unable_to_determine_ip_address));
    enableVoteButton(false);
    m_working = false;

    status_dialog.dismiss();
    RetryDialog();
}

// this is the dialog that informs the user that no IP was determined.
// clicking Retry will start the process of finding the IP again.
private void RetryDialog()
{
    Resources res = getResources();

    AlertDialog.Builder builder1 = new AlertDialog.Builder(MainActivity.this);
    builder1.setMessage(res.getString(R.string.status_unable_to_determine_ip_address));
    builder1.setCancelable(false);

    builder1.setPositiveButton(
            "Retry",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                    fetchIP();
                }
            });

    AlertDialog alert11 = builder1.create();
    alert11.show();

}

In DetermineIP.onPostExecute

protected void onPostExecute(String result) {
    if(result.isEmpty()) ((MainActivity) m_parent).setNoIP();
    else ((MainActivity) m_parent).setIP(result);
}

Upvotes: 0

Views: 305

Answers (2)

a_m
a_m

Reputation: 341

Any updates to the UI from an AsyncTask can be done in the following way -

protected void onPostExecute(Object result) {

            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //UI related code
                }
            });
        }

Upvotes: 1

j2emanue
j2emanue

Reputation: 62519

The error your getting highly suggest your doing work UI updates of the main UI thread. If you want to update the view you should do it on the UI thread. AsyncTask has a callback where you can update the UI if you want:

 @Override 
        protected void onPostExecute(Object result) {
        } 

and there is one for onPreExecute

Android's golden rule --> do heavy work on another thread (like do doInBackground of AsyncTask) and update UI on main thread.

So anything UI related just call it from the main thread not from asyncTask doInBackground

Upvotes: 0

Related Questions