Reputation: 18639
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
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
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
Reputation: 1336
I am quite certain that it's the Dialog that causing this issue as Chinmoy Debnath pointed out.
Upvotes: 2
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
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
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
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