Priyabrata
Priyabrata

Reputation: 1232

Android SurfaceHolder.getSurface Results in null pointer exception

I've been doing a little learning from youtube about android custom views and all. In my attempt to do a Surface View (rather simple as described in this video).

I've done things pretty much in sync with what was shown in the video.

How ever I am receiving a null pointer exception in the surfaceHolder.getSurface() .

Here is my entire code :

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


public class MainActivity extends AppCompatActivity {

    Ui ui;
    Bitmap ball;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        ui = new Ui(this);
        ball = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
        setContentView(ui);
    }

    @Override
    protected void onResume() {
        super.onResume();
        ui.resume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        ui.pause();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


    public class Ui extends SurfaceView implements Runnable {

        private Thread thread;
        private SurfaceHolder surfaceHolder;
        boolean ok = false;


        public Ui(Context context) {
            super(context);
            thread = null;
            surfaceHolder = getHolder();
        }

        @Override
        public void run() {
            while (ok) {
                if (!surfaceHolder.getSurface().isValid()) {
                    continue;
                }
                Canvas canvas = surfaceHolder.lockCanvas();
                canvas.drawARGB(200, 150, 130, 120);
                canvas.drawBitmap(ball, 0, 0, null);
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }

        public void pause() {
            ok = false;
            while (true) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                break;
            }
            thread = null;
        }

        public void resume() {
            ok = true;
            thread = new Thread(this);
            thread.run();
        }

    }
}

This part of the code :

Some pointer to what I am doing wrong will be helpful!.

@Override
            public void run() {
                while (ok) {
                    if (!surfaceHolder.getSurface().isValid()) {
                        continue;
                    }
                    Canvas canvas = surfaceHolder.lockCanvas();
                    canvas.drawARGB(200, 150, 130, 120);
                    canvas.drawBitmap(ball, 0, 0, null);
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }

The problem appears in this line :

if (!surfaceHolder.getSurface().isValid()) 

always returns false and the later part of the code is never executed.

Logcat :

06-25 15:23:46.211    2012-2012/com.pchakraverti.canvasapp D/AndroidRuntime﹕ Shutting down VM
06-25 15:23:46.211    2012-2012/com.pchakraverti.canvasapp W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xa62f8288)
06-25 15:23:46.211    2012-2012/com.pchakraverti.canvasapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to resume activity {com.pchakraverti.canvasapp/com.pchakraverti.canvasapp.MainActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2575)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089)
            at android.app.ActivityThread.access$600(ActivityThread.java:130)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            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:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at com.pchakraverti.canvasapp.Ui.run(Ui.java:44)
            at java.lang.Thread.run(Thread.java:856)
            at com.pchakraverti.canvasapp.Ui.resume(Ui.java:66)
            at com.pchakraverti.canvasapp.MainActivity.onPostResume(MainActivity.java:24)
            at android.app.Activity.performResume(Activity.java:5095)
            at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2565)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089)
            at android.app.ActivityThread.access$600(ActivityThread.java:130)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            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:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)
06-25 15:23:46.227    2012-2015/com.pchakraverti.canvasapp D/dalvikvm﹕ GC_CONCURRENT freed 208K, 3% free 10919K/11207K, paused 12ms+0ms, total 15ms
06-25 15:25:15.043    2067-2067/com.pchakraverti.canvasapp D/dalvikvm﹕ Late-enabling CheckJNI
06-25 15:25:15.091    2067-2070/com.pchakraverti.canvasapp D/dalvikvm﹕ GC_CONCURRENT freed 98K, 3% free 11074K/11335K, paused 11ms+0ms, total 23ms
06-25 15:25:15.095    2067-2067/com.pchakraverti.canvasapp D/dalvikvm﹕ GC_FOR_ALLOC freed <1K, 3% free 11073K/11335K, paused 4ms, total 4ms
06-25 15:25:15.131    2067-2067/com.pchakraverti.canvasapp I/dalvikvm-heap﹕ Grow heap (frag case) to 11.887MB for 1048588-byte allocation
06-25 15:25:15.155    2067-2070/com.pchakraverti.canvasapp D/dalvikvm﹕ GC_CONCURRENT freed 0K, 3% free 12097K/12423K, paused 15ms+0ms, total 22ms
06-25 15:25:15.155    2067-2067/com.pchakraverti.canvasapp D/dalvikvm﹕ WAIT_FOR_CONCURRENT_GC blocked 0ms
06-25 15:25:15.163    2067-2067/com.pchakraverti.canvasapp I/dalvikvm﹕ Could not find method android.view.ViewGroup.onRtlPropertiesChanged, referenced from method android.support.v7.widget.Toolbar.onRtlPropertiesChanged
06-25 15:25:15.163    2067-2067/com.pchakraverti.canvasapp W/dalvikvm﹕ VFY: unable to resolve virtual method 13337: Landroid/view/ViewGroup;.onRtlPropertiesChanged (I)V
06-25 15:25:15.163    2067-2067/com.pchakraverti.canvasapp D/dalvikvm﹕ VFY: replacing opcode 0x6f at 0x0007
06-25 15:25:15.163    2067-2067/com.pchakraverti.canvasapp I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.internal.widget.TintTypedArray.getChangingConfigurations
06-25 15:25:15.163    2067-2067/com.pchakraverti.canvasapp W/dalvikvm﹕ VFY: unable to resolve virtual method 408: Landroid/content/res/TypedArray;.getChangingConfigurations ()I
06-25 15:25:15.163    2067-2067/com.pchakraverti.canvasapp D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002
06-25 15:25:15.167    2067-2067/com.pchakraverti.canvasapp I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.internal.widget.TintTypedArray.getType
06-25 15:25:15.167    2067-2067/com.pchakraverti.canvasapp W/dalvikvm﹕ VFY: unable to resolve virtual method 430: Landroid/content/res/TypedArray;.getType (I)I
06-25 15:25:15.167    2067-2067/com.pchakraverti.canvasapp D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002
06-25 15:25:15.171    2067-2067/com.pchakraverti.canvasapp D/AndroidRuntime﹕ Shutting down VM
06-25 15:25:15.171    2067-2067/com.pchakraverti.canvasapp W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xa62f8288)
06-25 15:25:15.171    2067-2067/com.pchakraverti.canvasapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to resume activity {com.pchakraverti.canvasapp/com.pchakraverti.canvasapp.MainActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2575)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089)
            at android.app.ActivityThread.access$600(ActivityThread.java:130)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            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:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at com.pchakraverti.canvasapp.Ui.run(Ui.java:45)
            at java.lang.Thread.run(Thread.java:856)
            at com.pchakraverti.canvasapp.Ui.resume(Ui.java:66)
            at com.pchakraverti.canvasapp.MainActivity.onPostResume(MainActivity.java:24)
            at android.app.Activity.performResume(Activity.java:5095)
            at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2565)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089)
            at android.app.ActivityThread.access$600(ActivityThread.java:130)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            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:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)
06-25 15:26:56.039    2120-2125/com.pchakraverti.canvasapp I/dalvikvm﹕ threadid=3: reacting to signal 3

Upvotes: 1

Views: 2920

Answers (2)

fadden
fadden

Reputation: 52303

The SurfaceView has two parts, the Surface and the View. The Surface is created asynchronously, by the Window Manager, and you can't do anything with it until it's ready. You have to handle the SurfaceHolder.Callback methods to know when the Surface has been created and destroyed.

The SurfaceView lifecycle is not in lock step with the Activity life cycle, so you have to be a bit careful about allocating resources (like Camera) and starting / stopping threads. A discussion of the topic can be found in this appendix of the graphics architecture document. Various examples can be found in Grafika.

Please make sure that a SurfaceView is what you actually want. If you want a custom View, you should be working with View, not SurfaceView.

Upvotes: 1

zhangjie
zhangjie

Reputation: 331

please also look at this problem issued by myself, actually, it is very similar:
View.SurfaceView, why its member, mSurfaceHolder, returns null from getSurface()?
i also read the source code of SurfaceView.java in android sdk 22, but I noticed that member SurfaceView.mSurfaceHolder.getSurface() always returns null. That frastrates me!

Upvotes: 1

Related Questions