I am using the image crop library from here https://github.com/lvillani/android-cropimage in my project to crop images stored on device.
However, certain users are reporting crashes with the following stack trace
java.lang.UnsupportedOperationException
at android.view.GLES20Canvas.clipPath(GLES20Canvas.java:413)
at com.android.camera.HighlightView.draw(HighlightView.java:101)
at com.android.camera.CropImageView.onDraw(CropImage.java:783)
at android.view.View.draw(View.java:11006)
at android.view.View.getDisplayList(View.java:10445)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.getDisplayList(View.java:10443)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.getDisplayList(View.java:10443)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.getDisplayList(View.java:10443)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.getDisplayList(View.java:10443)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.draw(View.java:11009)
at android.widget.FrameLayout.draw(FrameLayout.java:450)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2154)
at android.view.View.getDisplayList(View.java:10445)
at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:853)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:1961)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1679)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2558)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4697)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
at dalvik.system.NativeStart.main(Native Method)
From searching I think it is caused by hardware acceleration on only certain devices. I have disable hardware acceleration in my manifest but the exception is still occurring. I have also found "A solid workaround is to identify the problematic operations in your code, draw those to a bitmap instead, then blit the bitmap to your accelerated canvas."
The problematic code according to the stack trace is
protected void draw(Canvas canvas) {
if (mHidden) {
return;
}
canvas.save();
Path path = new Path();
if (!hasFocus()) {
mOutlinePaint.setColor(0xFF000000);
canvas.drawRect(mDrawRect, mOutlinePaint);
} else {
Rect viewDrawingRect = new Rect();
mContext.getDrawingRect(viewDrawingRect);
if (mCircle) {
float width = mDrawRect.width();
float height = mDrawRect.height();
path.addCircle(mDrawRect.left + (width / 2),
mDrawRect.top + (height / 2),
width / 2,
Path.Direction.CW);
mOutlinePaint.setColor(0xFFEF04D6);
} else {
path.addRect(new RectF(mDrawRect), Path.Direction.CW);
mOutlinePaint.setColor(0xFFFF8A00);
}
canvas.clipPath(path, Region.Op.DIFFERENCE);
canvas.drawRect(viewDrawingRect,
hasFocus() ? mFocusPaint : mNoFocusPaint);
canvas.restore();
canvas.drawPath(path, mOutlinePaint);
if (mMode == ModifyMode.Grow) {
if (mCircle) {
int width = mResizeDrawableDiagonal.getIntrinsicWidth();
int height = mResizeDrawableDiagonal.getIntrinsicHeight();
int d = (int) Math.round(Math.cos(/*45deg*/Math.PI / 4D)
* (mDrawRect.width() / 2D));
int x = mDrawRect.left
+ (mDrawRect.width() / 2) + d - width / 2;
int y = mDrawRect.top
+ (mDrawRect.height() / 2) - d - height / 2;
mResizeDrawableDiagonal.setBounds(x, y,
x + mResizeDrawableDiagonal.getIntrinsicWidth(),
y + mResizeDrawableDiagonal.getIntrinsicHeight());
mResizeDrawableDiagonal.draw(canvas);
} else {
int left = mDrawRect.left + 1;
int right = mDrawRect.right + 1;
int top = mDrawRect.top + 4;
int bottom = mDrawRect.bottom + 3;
int widthWidth =
mResizeDrawableWidth.getIntrinsicWidth() / 2;
int widthHeight =
mResizeDrawableWidth.getIntrinsicHeight() / 2;
int heightHeight =
mResizeDrawableHeight.getIntrinsicHeight() / 2;
int heightWidth =
mResizeDrawableHeight.getIntrinsicWidth() / 2;
int xMiddle = mDrawRect.left
+ ((mDrawRect.right - mDrawRect.left) / 2);
int yMiddle = mDrawRect.top
+ ((mDrawRect.bottom - mDrawRect.top) / 2);
mResizeDrawableWidth.setBounds(left - widthWidth,
yMiddle - widthHeight,
left + widthWidth,
yMiddle + widthHeight);
mResizeDrawableWidth.draw(canvas);
mResizeDrawableWidth.setBounds(right - widthWidth,
yMiddle - widthHeight,
right + widthWidth,
yMiddle + widthHeight);
mResizeDrawableWidth.draw(canvas);
mResizeDrawableHeight.setBounds(xMiddle - heightWidth,
top - heightHeight,
xMiddle + heightWidth,
top + heightHeight);
mResizeDrawableHeight.draw(canvas);
mResizeDrawableHeight.setBounds(xMiddle - heightWidth,
bottom - heightHeight,
xMiddle + heightWidth,
bottom + heightHeight);
mResizeDrawableHeight.draw(canvas);
}
}
}
}
How can I draw to a bitmap and then blit to the canvas?
Any help would be greatly appreciated!
On ICS devices, there is a developer option to force hardware acceleration even if the app doesn't request it. That is what is causing the crashes. You should be able to use something like this to force it to use software rendering:
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
myCustomView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With