surfaceView.getHolder没有返回SurfaceHolder

8

我正在尝试编写一个使用相机的应用程序。当我尝试获取surfaceHolder并将其传递给surfaceCreated()以启动相机时,我遇到了NullPointerException。是否存在getHolder()返回NULL的情况?

谢谢。

package com.tecmark;

import java.io.IOException;

import android.app.Activity;

import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;

public class cameraView extends Activity implements SurfaceHolder.Callback{

    SurfaceView mSurfaceView;
    SurfaceHolder mSurfaceHolder;
    Camera mCamera;
    boolean mPreviewRunning;

 /** Called when the activity is first created. */
    @Override 
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        getWindow().setFormat(PixelFormat.TRANSLUCENT);

        requestWindowFeature(Window.FEATURE_NO_TITLE);

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

        WindowManager.LayoutParams.FLAG_FULLSCREEN);

        //setContentView(R.layout.camera_surface);   

        mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
        Log.i("surfaceholder = ", "about to get surface holder");
        try{
        mSurfaceHolder = mSurfaceView.getHolder();
        }catch(Exception e){
         e.printStackTrace();
        }

        Log.i("surfaceholder = ", ""+mSurfaceHolder.toString());

        mSurfaceHolder.addCallback(this);

        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        setContentView(R.layout.camera_surface);

        surfaceCreated(mSurfaceHolder);







    }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

  if (mPreviewRunning) {

   mCamera.stopPreview();

   }

   Camera.Parameters p = mCamera.getParameters();

   p.setPreviewSize(w, h);

   mCamera.setParameters(p);

   try {

   mCamera.setPreviewDisplay(holder);

   } catch (Exception e) {

   e.printStackTrace();

   }

   mCamera.startPreview();

   mPreviewRunning = true;

   }






 @Override
 public void surfaceCreated(SurfaceHolder holder) {




  try{
   Log.i("camera ", "about to open camera");
         mCamera = Camera.open();
         Log.i("camera ", " camera opened");
         mCamera.getParameters();
         mCamera.setPreviewDisplay(holder);
         mCamera.startPreview();
   } catch (IOException e) {

    e.printStackTrace();
   }
  Log.i("camera ", "ok");
 }

 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
  mCamera.stopPreview();

  mPreviewRunning = false;

  mCamera.release();

 }




}//end of activity



01-31 15:29:17.773: WARN/System.err(9144): java.lang.NullPointerException
01-31 15:29:17.778: WARN/System.err(9144):     at com.tecmark.cameraView.onCreate(cameraView.java:42)
01-31 15:29:17.778: WARN/System.err(9144):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-31 15:29:17.778: WARN/System.err(9144):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
01-31 15:29:17.783: WARN/System.err(9144):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
01-31 15:29:17.783: WARN/System.err(9144):     at android.app.ActivityThread.access$2200(ActivityThread.java:119)
01-31 15:29:17.783: WARN/System.err(9144):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
01-31 15:29:17.783: WARN/System.err(9144):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-31 15:29:17.783: WARN/System.err(9144):     at android.os.Looper.loop(Looper.java:123)
01-31 15:29:17.783: WARN/System.err(9144):     at android.app.ActivityThread.main(ActivityThread.java:4363)
01-31 15:29:17.783: WARN/System.err(9144):     at java.lang.reflect.Method.invokeNative(Native Method)
01-31 15:29:17.788: WARN/System.err(9144):     at java.lang.reflect.Method.invoke(Method.java:521)
01-31 15:29:17.788: WARN/System.err(9144):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
01-31 15:29:17.788: WARN/System.err(9144):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
01-31 15:29:17.788: WARN/System.err(9144):     at dalvik.system.NativeStart.main(Native Method)
01-31 15:29:17.793: DEBUG/AndroidRuntime(9144): Shutting down VM
01-31 15:29:17.793: WARN/dalvikvm(9144): threadid=3: thread exiting with uncaught exception (group=0x4001b180)
01-31 15:29:17.793: ERROR/AndroidRuntime(9144): Uncaught handler: thread main exiting due to uncaught exception
01-31 15:29:17.803: ERROR/AndroidRuntime(9144): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tecmark/com.tecmark.cameraView}: java.lang.NullPointerException
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at android.app.ActivityThread.access$2200(ActivityThread.java:119)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at android.os.Looper.loop(Looper.java:123)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at android.app.ActivityThread.main(ActivityThread.java:4363)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at java.lang.reflect.Method.invokeNative(Native Method)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at java.lang.reflect.Method.invoke(Method.java:521)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at dalvik.system.NativeStart.main(Native Method)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144): Caused by: java.lang.NullPointerException
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at com.tecmark.cameraView.onCreate(cameraView.java:47)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
01-31 15:29:17.803: ERROR/AndroidRuntime(9144):     ... 11 more
2个回答

15

重新开始回答,希望更加清晰明了。我认为根本问题在于你在onCreate和onResume中所执行的操作太多了。

我认为你遇到的根本问题是,有些视图/活动生命周期的部分需要运行它们自己的课程,然后才能处理surfaceView并开始预览。

我不确定这一点,但这里是我在一个工作的增强现实应用程序中处理各种相机和surface view相关内容的详细信息:

onCreate()
{
    // just set content view. do nothing with the camera or surfaceView yet
    setContentView(R.layout.main);
}

onResume()
{
        // open camera
    mCamera = Camera.open();

    // init surface view
    sv = (SurfaceView)this.findViewById(R.id.SurfaceView01);
            mHolder = sv.getHolder(); 
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
            mHolder.setSizeFromLayout();
            mHolder.addCallback(this); 
}

surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
    mCamera.setPreviewDisplay(holder);
    // set any cam params you need...

    mCamera.startPreview();
}
尝试重新组织您的代码以执行类似操作。从您的源代码中,我很难计算出NPE发生的位置,但我认为存在一些问题:
- 在调用setContentView()之前,您似乎正在尝试获取对surfaceview的引用 - 您直接调用了surfaceCreated方法,而不是通过回调让它被调用。
希望这能有所帮助。我们会想出解决方案的!

嘿,非常感谢你的帮助。相机现在可以工作了。我正在尝试让应用程序包括面部识别功能,所以现在要去看一下。我需要更好地了解SurfaceView和SurfaceHolder回调类,以了解需要实现哪些方法以及在哪里放置我的代码。再次感谢。 - turtleboy
如果我想发布新代码,我该怎么做?我需要编辑原始问题还是可以在评论中发布代码?谢谢。 - turtleboy
我认为你说得很对。主要问题在于他正在执行以下操作: mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera); 在调用 setContentView(R.layout.camera_surface); 之前。这可能会返回 mSurfaceView = null。 - Chrispix
我发现通过从SurfaceHolder.Callback设置预览可以解决很多问题 - 这样你只需要在Holder创建后再传入它(这可能需要一些时间)。 - Andrew Wyld

0

凭记忆所知,我认为你需要在onResume中执行SurfaceView相关的操作,而不是在onCreate中执行,否则看起来没问题。

另外,你应该尝试调用:

mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
mSurfaceHolder.setSizeFromLayout();

在开始预览之前,获取持有者的引用后立即执行。


好的,我已经将表面相关的内容放到onResume()中了,但仍然无法工作。我已经记录了surfaceholder和surfaceview对象,并且它们已经被实例化了。camera.open()方法被记录为正常。我得到了一些错误提示,说无法连接到相机服务,应用程序传递了null服务并且表面尚未设置。还有一个surface.OutOfResourcesException。看来surface没有从xml中设置。 - turtleboy
请查看有关PUSH_BUFFERS的更新答案。如果这不起作用,我会更深入地研究并与一些我正在使用的AR应用进行比较。 - mmeyer
好的,我之前尝试过使用setSizeFromLayout()。这是debug输出的结果。谢谢。 - turtleboy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接