We've started receiving this exception a bit more frequently than usual, and because the view had a custom name, it appeared in the stack trace as well, so I am lucky on that part. I've found some questions that have not been really answered (1, 2 and some others that did not receive any attention) so I'm asking a new question here.
Exception (from Android 6.0):
Fatal Exception: java.lang.IllegalStateException: Unable to create layer for MyCustomView
at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
at android.os.MessageQueue.next + 328(MessageQueue.java:328)
at android.os.Looper.loop + 164(Looper.java:164)
at android.app.ActivityThread.main + 5765(ActivityThread.java:5765)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run + 789(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main + 679(ZygoteInit.java:679)
Another exception (from Android 9.0):
Fatal Exception: java.lang.IllegalStateException: Unable to create layer for MyCustomView, size 768x0 max size 4096 color type 4 has context 1
at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
at android.os.MessageQueue.next + 326(MessageQueue.java:326)
at android.os.Looper.loop + 160(Looper.java:160)
at android.app.ActivityThread.main + 6819(ActivityThread.java:6819)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run + 497(RuntimeInit.java:497)
at com.android.internal.os.ZygoteInit.main + 912(ZygoteInit.java:912)
Related views in the layout (the view is in a wrap_content
RelativeLayout
which is a child of a ScrollView
):
<com.example.android.views.MyCustomView
android:id="@+id/backgroundView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignLeft="@id/actualContent"
android:layout_alignTop="@id/actualContent"
android:layout_alignRight="@id/actualContent"
android:layout_alignBottom="@id/actualContent"
android:layout_marginTop="3dp"
android:background="@color/backgroundColor"
android:visibility="gone" />
<include
android:id="@+id/actualContent"
layout="@layout/results_scroll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/progressLayout" />
Description of what the app and these layouts do:
These are the two views that are heavily animated (especially the view with the id @id/actualContent
). Its layout initially has a height of 0, where the progress passes its height increases. And, MyCustomView
is a background view to cover that area. When the progress reaches to 100, MyCustomView
gets animated with an AlphaAnimation
where its visibility changes from GONE --> VISIBLE
at the start of the animation. At this point @id/actualContent
has both width and height values more than 0.
The view with @id/actualContent
can exceed the screen height, and with that it will also allow MyCustomView
to exceed the height of the screen. Maybe this is the issue, but unfortunately the background is supposed to overlap with the main background of the root view (the ScrollView
) where it has some sort of blue-ish background, while that view has plain white. It needs to move with @id/actualContent
and cover the main scroll view background as the content scrolls. If the content is bigger than the screen height, would this cause the exception maybe?
The second exception gave me a hint that the cause is that the anchored view (@id/actualContent
) had 0 height and MyCustomView
was tried to be animated with 0 height as well. To make sure it's not the case, I even tried to implement something like this but it doesn't seem to work.
/**
* Checks the actual content layout width and height and attaches the runnable inside it,
* then runs the runnable afterwards. If width or height is 0, some devices can throw
* a native exception which cannot be traced back to here. It was only possible to find out
* because the view was named specially {@link com.example.android.views.MyCustomView}
* and we assume the problem can be solved through here.
*
* The runnable passed performs the background view animation.
*/
private void checkLayoutAndRun(@NonNull Runnable runnable)
{
View actualContent = findViewById(R.id.actualContent);
int width = actualContent.getWidth();
int height = actualContent.getHeight();
if (width == 0 || height == 0)
{
actualContent.addOnLayoutChangeListener(new View.OnLayoutChangeListener()
{
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
{
int width = right - left;
int height = bottom - top;
if (width >= 0 && height >= 0)
{
runnable.run();
v.removeOnLayoutChangeListener(this);
}
}
});
}
else
runnable.run();
}
I've also read that disabling hardware acceleration might help resolving the issue, but using setLayerType(View.LAYER_TYPE_SOFTWARE, null)
just makes the view disappear (because of AlphaAnimation
I assume) which is not the solution I'm looking for. I'm also not sure if overriding hasOverlappingRendering()
with the return value of false
will help but it is something I haven't tried yet (well, I did, works on my device but I cannot create any exceptions.)
I have multiple devices that has Android 9.0 in it (including mine) and yet I cannot reproduce these exceptions on my device, or any other emulators.
Any opinions? Thank you very much for your feedback.