Getting a null pointer exception while trying to draw on canvas textureview android?

0

I am trying to drawn on a TextureView with a canvas in Android. I am doing it inside a thread but for some reason, when I try to run my program, I am getting a null pointer exception. I have implemented my thread in the surfaceAvailable() callback but I'm still unable to draw. What could I be doing wrong?

This is what i tried so far:

public class MainActivity extends Activity implements TextureView.SurfaceTextureListener, Camera.PreviewCallback {

    private Camera mCamera;
    private TextureView mTextureView;
    Context mContext;
    private int[] pixels = null;
    private ImageView imageView;

    private MainActivity.RenderingThread mThread;




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        imageView = new ImageView(this);
        mTextureView = new TextureView(this);
        mTextureView.setSurfaceTextureListener(this);

        setContentView(mTextureView);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {


        DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
        int screenWidth = displayMetrics.widthPixels;
        int screenHeight = displayMetrics.heightPixels;

       int  mPreviewRate = Math.round((float)screenHeight / (float)screenWidth);
        mCamera = Camera.open();

        Camera.Size previewSize = mCamera.getParameters().getPreviewSize();

        mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
                previewSize.width*mPreviewRate, previewSize.height*mPreviewRate, Gravity.CENTER));

        try {
            mCamera.setPreviewTexture(surface);
        } catch (IOException t) {
        }

        mCamera.startPreview();


        mTextureView.setAlpha(1.0f);
        mTextureView.setRotation(90.0f);

        mThread = new RenderingThread(mTextureView);
        mThread.start();




    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        // Ignored, the Camera does all the work for us
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        mCamera.stopPreview();
        mCamera.release();
        if (mThread != null) mThread.stopRendering();
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        // Update your view here!

    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {



    }

    private static class RenderingThread extends Thread {
        private final TextureView mSurface;
        private volatile boolean mRunning = true;

        public RenderingThread(TextureView surface) {
            mSurface = surface;
        }

        @Override
        public void run() {
            float x = 0.0f;
            float y = 0.0f;
            float speedX = 5.0f;
            float speedY = 3.0f;

            Paint paint = new Paint();
            paint.setColor(0xff00ff00);

            while (mRunning && !Thread.interrupted()) {
                final Canvas canvas = mSurface.lockCanvas(null);
                try {
                    canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
                    canvas.drawRect(x, y, x + 20.0f, y + 20.0f, paint);
                } finally {
                    mSurface.unlockCanvasAndPost(canvas);
                }

                if (x + 20.0f + speedX >= mSurface.getWidth() || x + speedX <= 0.0f) {
                    speedX = -speedX;
                }
                if (y + 20.0f + speedY >= mSurface.getHeight() || y + speedY <= 0.0f) {
                    speedY = -speedY;
                }

                x += speedX;
                y += speedY;

                try {
                    Thread.sleep(15);
                } catch (InterruptedException e) {
                    // Interrupted
                }
            }
        }

        void stopRendering() {
            interrupt();
            mRunning = false;
        }

    }

}

This is my stacktrace:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int, android.graphics.PorterDuff$Mode)' on a null object reference
java
android
textureview
asked on Stack Overflow Aug 18, 2018 by anastacia das • edited Aug 18, 2018 by Talendar

1 Answer

1

I believe the problem is here:

final Canvas canvas = mSurface.lockCanvas(null);

Take a look at the official documentation:

lockCanvas

public abstract Canvas lockCanvas ()

Start editing the pixels in the surface. The returned Canvas can be used to draw into the surface's bitmap. A null is returned if the surface has not been created or otherwise cannot be edited. You will usually need to implement Callback.surfaceCreated to find out when the Surface is available for use.

You might be trying to draw on a surface before it has been created. In this case, you must make sure that lockCanvas() is only called after the surface is ready (listen for the surface creation). Also, in your case, you should use the lockCanvas() without arguments, like this:

final Canvas canvas = mSurface.lockCanvas();
answered on Stack Overflow Aug 18, 2018 by Talendar

User contributions licensed under CC BY-SA 3.0