views:

161

answers:

4

I am developing one application in which i am getting an exception, and i know this one is the silly or small mistake which i am doing but your help may catch me out and make my day:

public class Demo extends Activity
{
    Button btnDemo;
        Thread t;
    AlertDialog alertDialog;

     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.demo);

              btnDemo = (Button) findViewById(R.id.btnDemo);
          btnDemo.setOnClickListener(new OnClickListener() {
                      public void onClick(final View v) {

                          t=new Thread() {
                               public void run() {
                                    tryDemo();
                               }
                         };
                         t.start(); 
                      }
                });
     }

    public void tryDemo()
    {

          try
         {
              int i = 5;

              if(i == 0 || i == 1)
              {
                    Intent intent_success = new Intent(getApplicationContext(), Main_Activity.class);
                    startActivity(intent_success);
              }
              else
              {
                alertDialog = new  AlertDialog.Builder(getApplicationContext()).create();
                alertDialog.setTitle("Demo");
                alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int which) {
                       //here you can add functions
                } }); 
                alertDialog.setIcon(R.drawable.icon);
                alertDialog.setMessage("Sorry!! Either Username or Password Invalid");
                alertDialog.show();

              }
         }
         catch(Exception e)
         {
               Log.i("Demo", "Demo - Demo Exception");
         }
    }   
}

In above code, if i make i=0 or i=1 in tryDemo function then it is running successfully , but if i make it other than 0 or 1 then it throws an exception as "Demo - Demo Exception".

I am not sure but i think the exception raises from getApplicationContext().

Update:- 1

The exception which i am getting, as follows:

alt text

Update:- 2 If I remove the "thread" part and wrote the whole function code in the button click event and replaced the "getApplicationContext()" with v.getContext() then it is running successfully.........but i want to implement it within the THREAD.

Please help me and catch me out...

thanx

A: 

You are probably getting a RuntimeException. I tried calling some dialog creation in a thread not being the UI thread and got this:

09-09 00:46:37.702: ERROR/AndroidRuntime(763): Uncaught handler: thread Thread-10 exiting due to uncaught exception
09-09 00:46:37.724: ERROR/AndroidRuntime(763): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
09-09 00:46:37.724: ERROR/AndroidRuntime(763):     at android.os.Handler.<init>(Handler.java:121)
09-09 00:46:37.724: ERROR/AndroidRuntime(763):     at android.view.ViewRoot.<init>(ViewRoot.java:192)
09-09 00:46:37.724: ERROR/AndroidRuntime(763):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
09-09 00:46:37.724: ERROR/AndroidRuntime(763):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
09-09 00:46:37.724: ERROR/AndroidRuntime(763):     at android.view.Window$LocalWindowManager.addView(Window.java:392)
09-09 00:46:37.724: ERROR/AndroidRuntime(763):     at android.app.Dialog.show(Dialog.java:231)
09-09 00:46:37.724: ERROR/AndroidRuntime(763):     at com.pkg.name.ToplistActivity$3.run(ToplistActivity.java:149)

Solution is to wrap your else statement like:

else {
    runOnUiThread(new Runnable() {
        public void run() {
            ...
        }
    });
}
Key
@Key thanx for the answer and let me try it out.....
PM - Paresh Mayani
@Key i have wrapped else as you told but now its throwing new error: tag => AndroidRunTime , Error Message => android.view.WindowManager$BadTokenException: Unable to add window......
PM - Paresh Mayani
@Paresh Mayani: Hard to know without showing the new code and the exception. Update the question.
Key
@Key i have indicated "update" question
PM - Paresh Mayani
@Paresh Mayani: I can't see any update to the question..?
Key
+1  A: 

Just read your logs :D You haven't called the Looper.prepare()

If I am correct, you should wrap your AlertDialog code with Looper.prepare() and Looper.loop()

So it looks like:

Looper.prepare()
// AlertDialog code
Looper.loop()
LordTwaroog
@KLordTwaroog i have wrapped AlertDialog code as you told but now its throwing exception: tag => AndroidRunTime , Message => android.view.WindowManager$BadTokenException: Unable to add window......
PM - Paresh Mayani
I use the activity context to create AlertDialogs in my code. Also, I am not sure, if the AlertDialog shouldn't be running on UI thread.
LordTwaroog
+1  A: 

Checkout comments in this post:

http://stackoverflow.com/questions/987072/using-application-context-everywhere

Also if you replace getApplicationContext() with actiivtyname.getApplicationContext() what errors are you getting?

Fred Grott
+1  A: 

A few things wrong with this. First, you never, EVER touch any UI elements from any thread you've created.

You'll need to get aquatinted with thread Handlers: http://developer.android.com/reference/android/os/Handler.html

The way they work is, you initialize them in your normal UI thread. (the thread your onCreate() method is called.) Handlers, are thread safe objects that you extend to communicate between thread.

So, on your onCreate():

Handler pHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            Bundle bundle = msg.getData();
            int msg_type = bundle.getInt("TYPE");
            if (msg_type == MyThread.ERROR_MSG)
            {
                 ///SOMETHING HAPPENED
                 return;
            }
            else
            {
                //background task finished ok
            }
        }
    };

Then, from your run() method you send it a message using a Bundle and Message object. http://developer.android.com/reference/android/os/Bundle.html and http://developer.android.com/reference/android/os/Message.html

The way I like to do it, to keep things clean is to extend the Thread class to add a little consistency...

class MyThead extends Thread
{
    public final int ERROR_MSG = 0;
    public final int OK_MSG = 1;
    Handler mHandler;

    MyThread(Handler pHandler)
    {
        mHandler = pHandler;
    }

    @Override
    public void run()
    {
        //send a message back to the ui thread....
        Message msg = new Message();
        Bundle bundle = new Bundle();
        bundle.putInt("TYPE", OK_MSG);
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    }
}

This if you want to get a bit fancy, you separate the UI code and the worker thread code completely. If your background task won't take long, you can us runonUiThread() as previous described.

You might also want to use AsyncTask, see: http://developer.android.com/reference/android/os/AsyncTask.html

Here's an example from their page, its usage is rather simple:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

Eventually though, these approaches aren't perfect if the user changes orientation when your task is running. (or if your activity is killed for any other reason.) In that case, you'll want to set up a service: http://developer.android.com/reference/android/app/Service.html

Miguel Morales