Genadinik
Genadinik

Reputation: 18639

Android - rare runtime exception that does not point to any class where it starts

I am getting this runtime exception about once every thousand+ sessions on the app, so it is rare and I have not been able to reproduce it.

java.lang.IllegalArgumentException: View not attached to window manager
        at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:381)
        at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:226)
        at android.view.Window$LocalWindowManager.removeView(Window.java:432)
        at android.app.Dialog.dismissDialog(Dialog.java:278)
        at android.app.Dialog.access$000(Dialog.java:71)
        at android.app.Dialog$1.run(Dialog.java:111)
        at android.os.Handler.handleCallback(Handler.java:587)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:130)
        at android.app.ActivityThread.main(ActivityThread.java:3691)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:507)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:670)
        at dalvik.system.NativeStart.main(Native Method)

Would anyone know how to reproduce it, or why it happens? Or better yet, how to fix it? :)

Thanks!

EDIT:

I added the suggestion made by Raghav to add this:

<activity android:label="@string/app_name" 
        android:configChanges="orientation|keyboardHidden" 
        android:name="ActivityName">

But this has not fixed the crashing and the crashing is still happening.

EDIT:

Here is some typical code I use:

public class ProblemActivity extends BaseListActivity
{
    Dialog dialog;

        ....


@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);

    ...

    // After some action
    dialog.show();
}

public class GetSolutionTopicsTask extends AsyncTask<String, Void, String> 
{
    @Override
    protected String doInBackground(String... theParams) 
    {
        String myUrl = theParams[0];
        String problem_id = theParams[1];

        String charset = "UTF-8";           
        String response = null;

        try 
        {               
            String query = String.format("problem_id=%s", 
                     URLEncoder.encode(problem_id, charset));

            final URL url = new URL( myUrl + "?" + query );

            final HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            conn.setDoOutput(true); 
            conn.setRequestMethod("POST");

            conn.setDoOutput(true);
            conn.setUseCaches(false);

            conn.connect();

            final InputStream is = conn.getInputStream();
            final byte[] buffer = new byte[8196];
            int readCount;
            final StringBuilder builder = new StringBuilder();
            while ((readCount = is.read(buffer)) > -1) 
            {
                builder.append(new String(buffer, 0, readCount));
            }

            response = builder.toString();      
        } 
        catch (Exception e) 
        {

        }

        return response;
    }

    @Override
    protected void onPostExecute(String result) 
    {           
        if ( result == null  )
        {
            try 
            {
                dialog.dismiss();
            } catch (Exception e) {
                // nothing
            }

        }
        else
        {
            try 
            {
                    dialog.dismiss();
                } 
            catch (Exception e) 
            {
                // nothing
                }    
         }  // End of else

}        
}        

Upvotes: 4

Views: 851

Answers (7)

Abhishek Nandi
Abhishek Nandi

Reputation: 4275

ConfigChanges are not causing this issue.

From the above logs it seems, that a dialog which was displayed in the activity was being dismissed after the activity is no longer visible.

If you shared the code or atleast give the steps you perform to get the crash, I can suggest a fix.

Upvotes: 4

Digvesh Patel
Digvesh Patel

Reputation: 6533

private class LongOperation extends AsyncTask<String, Void, String> {

  @Override
  protected String doInBackground(String... params) {
     String response = "";

     for(int i=0;i<5;i++) {
         try {
             response =i;
             Thread.sleep(1000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }

     return response;
  }      

  @Override
  protected void onPostExecute(String result) { 
     TextView txt = (TextView) findViewById(R.id.output);
     txt.setText(result); 
  }

  @Override
  protected void onPreExecute() {

  }

  @Override
  protected void onProgressUpdate(Void... values) {

  }

}

Change it with your code. It's version issue. After version three we do not set view in main thread so we have to use async task...

Upvotes: 2

Nitin Sethi
Nitin Sethi

Reputation: 1336

I am quite certain that it's the Dialog that causing this issue as Chinmoy Debnath pointed out.

Upvotes: 2

Chinmoy Debnath
Chinmoy Debnath

Reputation: 2824

In some devices and also some cases activity gets finished before dialog successfully dismisses or asynchronous task is running in background , so when you call the dialoge to dismiss it causes

java.lang.IllegalArgumentException: View not attached to window manager

as the main ui thread is already dismissed.

In order to solve this you can track if the activity finished , so make the dialog null in onStop of the activity and then in onPostExecute check the status of the dialog; Code will be like

@Override
public void onStop() {
    super.onStop();
    dialog = null;
}

and in onpostexecute

if (dialog != null) { 
        dialog.dismiss();
   }

Upvotes: 3

Abhishek Nandi
Abhishek Nandi

Reputation: 4275

In onStop of the activity dimiss the dialog. Additionally before calling dismiss check

dialog.isShowing() is true or not.

if(dialog.isShowing())dialog.dismiss();

From the source code

private int  findViewLocked(View view, boolean required){       
    synchronized (this){        
        final int count = mViews != null ? mViews.length : 0;
        for (int i=0; i<count; i++) {               
            if (mViews[i] == view) { 
                return i;               
            }
        }           
        if (required) {             
            throw new IllegalArgumentException( "View not attached to window manager");         
        } 
        return -1;      
    }   
}

Since you are getting this exception it means that the view is not found when dismiss is called.

Upvotes: 2

Techwolf
Techwolf

Reputation: 1228

Do you use an AsyncTask that could finish after the activity is destroyed? android View not attached to window manager has some answers.

Also, if your application targets API 13 or higher, you should use this in your manifest instead of Raghav's suggestion (the screen size changes with the orientation in newer APIs):

    <activity android:label="@string/app_name" 
    android:configChanges="orientation|keyboardHidden|screenSize" 
    android:name="ActivityName">

Upvotes: 2

Raghav Sood
Raghav Sood

Reputation: 82563

When you switch orientations, Android will create a new View. You're probably getting crashes because your background thread is trying to change the state on the old one. (It may also be having trouble because your background thread isn't on the UI thread)

In your specific case, it seems you are trying to dismiss a dialog when it happens, probably from an AsyncTask or a background Thread.

To fix it, try the following:

<activity android:label="@string/app_name" 
        android:configChanges="orientation|keyboardHidden" 
        android:name="ActivityName">

The matter is that the system destroys the activity when a change in the configuration occurs. See ConfigurationChanges.

So putting that in the configuration file avoids the system to destroy your activity. Instead it invokes the onConfigurationChanged(Configuration) method.

There is also a similar and older question here, with more solutions. My current answer is a mix of two answers from there.

Upvotes: 2

Related Questions