1

Quite new in Android development, I keep getting a window leak exception, probably due to use of an alertbox I made. In searching for what I have to change, I tried a bunch of things and I can't find my error. Maybe someone can help me look through my code?

public class LogInActivity extends Activity {
    EditText gebruikersnaamET, paswoordET;
    TextView titel;
    TextView gebruikersnaamTV;
    TextView paswoordTV;
    TextView geenAccount;
    Button ok;
    String url = "";
    final Context context = this;
    String username = "";
    SharedPreferences settings;
    AlertBox alert;
    Gebruiker g = null;
    private ProgressDialog pDialog;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // http://stackoverflow.com/questions/4544302/android-prevent-user-from-coming-back-to-login-page-after-logging-in
        settings = context.getSharedPreferences("CoNeePrefs", 0);
        boolean isLogged = settings.getBoolean("isLogged", false);

        setTitle("Log in");
        setContentView(R.layout.activity_log_in);

        gebruikersnaamET = (EditText) findViewById(R.id.et_un);
        gebruikersnaamET.requestFocus();
        gebruikersnaamET.setTypeface(MyFonts.Fonts.PRESSTART);

        paswoordET = (EditText) findViewById(R.id.et_pw);
        paswoordET.setTypeface(MyFonts.Fonts.PRESSTART);

        ok = (Button) findViewById(R.id.btn_login);
        ok.setTypeface(MyFonts.Fonts.PRESSTART);

        titel = (TextView) findViewById(R.id.titel);
        // titel.setTypeface(MyFonts.Fonts.PRESSTART);
        Typeface face;
        face = Typeface.createFromAsset(getAssets(), "fonts/pressstart.ttf");
        titel.setTypeface(face);

        gebruikersnaamTV = (TextView) findViewById(R.id.tv_un);
        gebruikersnaamTV.setTypeface(MyFonts.Fonts.PRESSTART);

        paswoordTV = (TextView) findViewById(R.id.tv_pw);
        paswoordTV.setTypeface(MyFonts.Fonts.PRESSTART);

        geenAccount = (TextView) findViewById(R.id.nogGeenAccount);
        geenAccount.setTypeface(MyFonts.Fonts.PRESSTART);

        g = new Gebruiker();

        if (isLogged) {
            Intent intent = new Intent(context, MenuActivity.class);
            intent.putExtra("gebruikersnaam",
                    settings.getString("gebruikersnaam", "none"));
            startActivity(intent);
            finish();
        } else {
            ok.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub

                    new checkUserDetails().execute();
                }
            });

        }

        geenAccount.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                Intent intent = new Intent(context, RegisterActivity.class);
                startActivity(intent);
                finish();
            }
        });

    }

    // http://www.androidhive.info/2012/05/how-to-connect-android-with-php-mysql/
    class checkUserDetails extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(LogInActivity.this);
            pDialog.setMessage("In aan het loggen...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Getting product details in background thread
         * */
        protected String doInBackground(String... params) {

            url = "http://iwtsl.ehb.be/~iris.vdz/check.php";
            ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
            postParameters.add(new BasicNameValuePair("gebruikersnaam",
                    gebruikersnaamET.getText().toString()));
            postParameters.add(new BasicNameValuePair("paswoord", paswoordET
                    .getText().toString()));
            // String valid = "1";
            String res = null;
            String username = gebruikersnaamET.getText().toString();

            try {
                res = DatabaseAccess.getInstance().phpUitvoeren(postParameters,
                        url);

                if (res.equals("1")) {
                    g = DatabaseAccess.getInstance().getUser(username);
                    String adres = g.getStraat() + " - " + g.getPostcode()
                            + " " + g.getGemeente();
                    String volledigeNaam = g.getVoornaam() + " " + g.getNaam();
                    settings = context.getSharedPreferences("CoNeePrefs", 0);
                    SharedPreferences.Editor editor = settings.edit();
                    editor.putBoolean("isLogged", true);
                    editor.putString("gebruikersnaam", g.getGebruikersnaam());
                    editor.putString("naam", volledigeNaam);
                    editor.putString("e-mail", g.getEmail());
                    editor.putString("adres", adres);
                    editor.putString("paswoord",
                            g.getEncodedPaswoord(g.getPaswoord()));
                    editor.commit();

                    Intent intent = new Intent(context, MenuActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    alert = new AlertBox(context, "Error",
                            "Er is iets misgegaan, probeer opnieuw!\nMogelijke redenen:\n"
                                    + "- u heeft geen internetverbinding\n"
                                    + "- u heeft geen juiste login ingegeven\n"
                                    + "- er is een probleem met het netwerk\n"
                                    + "- er is een probleem met de database");
                }

            } catch (Exception e) {
                alert = new AlertBox(context, "Error", e.toString());

            }

            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog
         * **/
        protected void onPostExecute(String file_url) {
            // dismiss the dialog once got all details
            pDialog.dismiss();
        }
    }

This is the code for the AlertBox:

public class AlertBox {

    public AlertBox(Context context, String title, String mymessage){
         new AlertDialog.Builder(context)
          .setMessage(mymessage)
          .setTitle(title)
          .setCancelable(true)
          .setNeutralButton(android.R.string.cancel,
             new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int whichButton){

             }})
          .show();
    }
}

this is the stack-trace i'm getting:

04-07 14:31:28.230: E/AndroidRuntime(10287): FATAL EXCEPTION: AsyncTask #1
04-07 14:31:28.230: E/AndroidRuntime(10287): java.lang.RuntimeException: An error occured while executing doInBackground()
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.os.AsyncTask$3.done(AsyncTask.java:200)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.lang.Thread.run(Thread.java:1019)
04-07 14:31:28.230: E/AndroidRuntime(10287): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.os.Handler.(Handler.java:121)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.app.Dialog.(Dialog.java:101)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.app.AlertDialog.(AlertDialog.java:63)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.app.AlertDialog$Builder.create(AlertDialog.java:797)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.app.AlertDialog$Builder.show(AlertDialog.java:812)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at be.iwt.ehb.conee.extrafeatures.AlertBox.(AlertBox.java:20)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at be.iwt.ehb.conee.activities.LogInActivity$checkUserDetails.doInBackground(LogInActivity.java:178)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at be.iwt.ehb.conee.activities.LogInActivity$checkUserDetails.doInBackground(LogInActivity.java:1)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at android.os.AsyncTask$2.call(AsyncTask.java:185)
04-07 14:31:28.230: E/AndroidRuntime(10287):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
04-07 14:31:28.230: E/AndroidRuntime(10287):    ... 4 more
04-07 14:31:28.661: W/IInputConnectionWrapper(10287): showStatusIcon on inactive InputConnection
04-07 14:31:28.681: D/dalvikvm(10287): GC_CONCURRENT freed 200K, 49% free 2915K/5639K, external 303K/558K, paused 18ms+62ms
04-07 14:31:29.381: E/WindowManager(10287): Activity be.iwt.ehb.conee.activities.LogInActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40538cb0 that was originally added here
04-07 14:31:29.381: E/WindowManager(10287): android.view.WindowLeaked: Activity be.iwt.ehb.conee.activities.LogInActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40538cb0 that was originally added here
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.ViewRoot.(ViewRoot.java:259)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.Window$LocalWindowManager.addView(Window.java:465)
04-07 14:31:29.381: E/WindowManager(10287):     at android.app.Dialog.show(Dialog.java:241)
04-07 14:31:29.381: E/WindowManager(10287):     at be.iwt.ehb.conee.activities.LogInActivity$checkUserDetails.onPreExecute(LogInActivity.java:127)
04-07 14:31:29.381: E/WindowManager(10287):     at android.os.AsyncTask.execute(AsyncTask.java:391)
04-07 14:31:29.381: E/WindowManager(10287):     at be.iwt.ehb.conee.activities.LogInActivity$1.onClick(LogInActivity.java:96)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.View.performClick(View.java:2506)
04-07 14:31:29.381: E/WindowManager(10287):     at android.view.View$PerformClick.run(View.java:9112)
04-07 14:31:29.381: E/WindowManager(10287):     at android.os.Handler.handleCallback(Handler.java:587)
04-07 14:31:29.381: E/WindowManager(10287):     at android.os.Handler.dispatchMessage(Handler.java:92)
04-07 14:31:29.381: E/WindowManager(10287):     at android.os.Looper.loop(Looper.java:130)
04-07 14:31:29.381: E/WindowManager(10287):     at android.app.ActivityThread.main(ActivityThread.java:3835)
04-07 14:31:29.381: E/WindowManager(10287):     at java.lang.reflect.Method.invokeNative(Native Method)
04-07 14:31:29.381: E/WindowManager(10287):     at java.lang.reflect.Method.invoke(Method.java:507)
04-07 14:31:29.381: E/WindowManager(10287):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
04-07 14:31:29.381: E/WindowManager(10287):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
04-07 14:31:29.381: E/WindowManager(10287):     at dalvik.system.NativeStart.main(Native Method)

Thanks a lot in advance!

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
Iris_vdz
  • 251
  • 1
  • 8
  • 23

1 Answers1

0

The window leak is not the root cause of your crash; the primary problem here is that you're trying to create a dialog from a background thread:

Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

In AlertBox, you're creating a new dialog, which in turn contain their own Handler:

new AlertDialog.Builder(context)
          [...]
          .show();

However, you're creating AlertBox from your AsyncTask's doInBackground():

new AlertBox(context, "Error", e.toString());

Move that logic into the main thread, for instance by handling the error in onPostExecute().

Secondarily, you're getting the "window leaked" message because the AsyncTask is still running while the activity is gone, and it contains references to objects attached to that window, specifically pDialog.

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187