Android Canvas locking throws IllegalArgumentException

I am trying to implement my own custom SurfaceView that, when touched, draws a circle at the point where the user touched the screen. However, when I call mSurfaceHolder.lockCanvas() I get an exception. Something along the lines of an illegal argument whenever the canvas locks. Sample code is posted below.

public class TapArea extends SurfaceView implements SurfaceHolder.Callback {
    private static final int TAP_RADIUS = 4;
    private boolean mLoaded = false;
    private Paint mTapPaint;
    private SurfaceHolder mSurfaceHolder;

    protected OnTouchListener mTouchEvent = new OnTouchListener() {
        @Override
        public boolean onTouch(View arg0, MotionEvent arg1) {
            if (!mLoaded)
                return false;

            Canvas c = null;
            c = mSurfaceHolder.lockCanvas();
            drawTap(c, arg1);

            return true;
        }
    };

    public TapArea(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.setOnTouchListener(mTouchEvent);
        mHandler = new Handler();
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);
        mTapPaint = new Paint();
    }

    public void drawTap(Canvas canvas, MotionEvent tap) {
        canvas.drawCircle(tap.getX(), tap.getY(), TAP_RADIUS, mTapPaint);
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        // TODO Auto-generated method stub
        mLoaded = true;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        // TODO Auto-generated method stub

    }
}

Below are the error logs I keep getting:

  • Full Android support for OSGi bundles
  • App not in search results on Google Play
  • Combining Firebase realtime data listener with RxJava
  • How do you build an Android back stack when an activity is started directly from a notification?
  • How to add an image to the emulator gallery in android studio?
  • How do you obtain a Drawable object from a resource id in android package?
  • 01-17 00:19:44.703: E/Surface(9731): Surface::lock failed, already locked
    01-17 00:19:44.796: E/SurfaceHolder(9731): Exception locking surface
    01-17 00:19:44.796: E/SurfaceHolder(9731): java.lang.IllegalArgumentException
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.Surface.lockCanvasNative(Native Method)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.Surface.lockCanvas(Surface.java:314)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.SurfaceView$3.internalLockCanvas(SurfaceView.java:762)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.SurfaceView$3.lockCanvas(SurfaceView.java:741)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.frequency.FreqTapArea$2.onTouch(FreqTapArea.java:54)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.View.dispatchTouchEvent(View.java:3897)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1737)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1153)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.app.Activity.dispatchTouchEvent(Activity.java:2096)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1721)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2200)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1884)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.os.Handler.dispatchMessage(Handler.java:99)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.os.Looper.loop(Looper.java:130)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at android.app.ActivityThread.main(ActivityThread.java:3835)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at java.lang.reflect.Method.invokeNative(Native Method)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at java.lang.reflect.Method.invoke(Method.java:507)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
    01-17 00:19:44.796: E/SurfaceHolder(9731):  at dalvik.system.NativeStart.main(Native Method)
    

    Help would be greatly appreciated.

    Related posts:

    Passing function as a parameter in java
    Android - Losing incoming (hi-speed) USB data
    android studio : lambda expressions are not supported in -source 1.7 (use -source 8 or higher to ena...
    How to launch the Google Play intent in 'Give Feedback' mode on Android?
    Using GSON to parse json object vs json array
    How To Use Javascript to Detect When Phonegap-based Android App Loses Focus
  • ADB + Samsung Galaxy
  • Purpose of Service Intent-Filter inside Manifest.xml
  • Eclipse Android XML jumps around the editor
  • How to debug javascript in webview in android
  • Should I use android: process =“:remote” in my receiver?
  • Why does the “download completed” notification disappear on Gingerbread devices?
  • One Solution collect form web for “Android Canvas locking throws IllegalArgumentException”

    You need to unlock the canvas after drawing on it.
    The right secuence is:

    1. get de canvas calling mSurfaceHolder.lockCanvas();
    2. draw on canvas.
    3. unlock canvas calling mSurfaceHolder.unlockCanvasAndPost(c);

    In your code could be:

    public boolean onTouch(View arg0, MotionEvent arg1) {
            if (!mLoaded)
                return false;
    
            Canvas c = mSurfaceHolder.lockCanvas();
            drawTap(c, arg1);
            mSurfaceHolder.unlockCanvasAndPost(c);
    
            return true;
        }
    
    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.