Question

My view is a bunch of normal widget and a surfaceview. I don't know why after I get surfaceholder of SurfaceView and use getSurface() again on holder, I will always return null.

Here is my example code :

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.view);
    }

    @Override
    public void onResume() {
        super.onResume();
        surface = (SurfaceView) findViewById(R.id.surfaceView);
        this.holder = surface.getHolder();

         if (holder.getSurface().isValid()){  // get surface again
             Log.i("Notice","Surface holder is valid");
         }
         else
             Log.i("Notice","Surface holder ISNOT valid");  //Always receive this
        }

When I see Android document for getSurface() method. This is how it say:

Direct access to the surface object. The Surface may not always be available -- for example when using a SurfaceView the holder's Surface is not created until the view has been attached to the window manager and performed a layout in order to determine the dimensions and screen position of the Surface. You will thus usually need to implement Callback.surfaceCreated to find out when the Surface is available for use.

I don't understand this so much but I know I have miss something. Please explain for me, and tell me about Callback.surfaceCreated means, and how to implement it ?

Thanks :)

Was it helpful?

Solution

You are trying to use surface when it is not available yet. That's alright it is not available at your Activity.onCreate or Activity.onResume methods because actually surface is placed in separate window behind your Activity window and has own lifecycle. You need to implement SurfaceHolder.Callback to receive events about Surface availability and do drawing from a separate thread. Look at LunarLander project in Android SDK samples folder, it is shown there how to use SurfaceView properly.

Your callback will look something like that:

public class MyCallback implements SurfaceHolder.Callback {
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, 
        int width, int height) {    
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // you need to start your drawing thread here
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {  
        // and here you need to stop it
    }
}

And than you need to set this callback to SurfaceHolder:

surface.getHolder().addCallback(new MyCallback());

OTHER TIPS

i found solution, this worked for me, infect error is in choosing correct size , so while using MediaRecorder.setVideoSize() use this method to choose optimal size

private static Size chooseOptimalSize(Size[] choices, int width, int height) {
        Size bigEnough = null;
        int minAreaDiff = Integer.MAX_VALUE;
        for (Size option : choices) {
            int diff = (width*height)-(option.getWidth()*option.getHeight()) ;
            if (diff >=0 && diff < minAreaDiff &&
                    option.getWidth() <= width &&
                    option.getHeight() <= height) {
                minAreaDiff = diff;
                bigEnough = option;
            }
        }
        if (bigEnough != null) {
            return bigEnough;
        } else {
            Arrays.sort(choices,new CompareSizeByArea());
            return choices[0];
        }

    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top