Android 在Nexus 5中使用SurfaceView时应用程序崩溃

Android 在Nexus 5中使用SurfaceView时应用程序崩溃,android,android-camera,flashlight,nexus-5,Android,Android Camera,Flashlight,Nexus 5,我正在尝试制作一个简单的手电筒应用程序,可以在所有Android设备上运行,包括Nexus5(它要求我实现SurfaceView) 但我的应用程序每次运行都会崩溃。我做错了什么 我的完整代码如下: public class MainActivity extends Activity implements Callback { //flag to detect flash is on or off private boolean isLighOn = false; pri

我正在尝试制作一个简单的手电筒应用程序,可以在所有Android设备上运行,包括Nexus5(它要求我实现
SurfaceView

但我的应用程序每次运行都会崩溃。我做错了什么

我的完整代码如下:

public class MainActivity extends Activity implements Callback {

    //flag to detect flash is on or off
    private boolean isLighOn = false;
    private Camera camera;
    private Button button;
    private Parameters p;
    private SurfaceHolder mHolder;
    @Override

    protected void onStart() {
        super.onStart();

        SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW);
            SurfaceHolder mHolder = preview.getHolder();
            mHolder.addCallback(this);
    }

    @Override
    protected void onStop() {
        super.onStop();

        if (camera != null) {
            camera.release();
        }
    }

    @Override   
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Context context = this;
        PackageManager pm = context.getPackageManager();

        // if device support camera?
        if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            Log.e("err", "Device has no camera!");
            return;
        }
        camera = Camera.open();
        final Parameters p = camera.getParameters();

        final ToggleButton tb = (ToggleButton) findViewById(R.id.toggle);
        final ImageView image = (ImageView) findViewById(R.id.photo);
        tb.setText(null);
        tb.setTextOn(null);
        tb.setTextOff(null);
        tb.setBackgroundResource(R.drawable.check);

        tb.setOnClickListener(new View.OnClickListener() {          
            @Override
            public void onClick(View v) {
                if (tb.isChecked()) {
                    image.setImageResource(R.drawable.b);   
                    turnOffFlash();
                } else {
                    image.setImageResource(R.drawable.a);                       
                }                   
            }
        });
    }

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

    private void turnOnFlash(){
        Log.i("info", "torch is turn on!");

        p.setFlashMode(Parameters.FLASH_MODE_TORCH);

        camera.setParameters(p);
        camera.startPreview();
        isLighOn = true;
    }

    private void turnOffFlash(){
        Log.i("info", "torch is turn off!");

        p.setFlashMode(Parameters.FLASH_MODE_OFF);
        camera.setParameters(p);
        camera.stopPreview();
        isLighOn = false;
    }           

    @Override
    public void surfaceChanged(SurfaceHolder holder,int format,int width,int height)   {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder){
        mHolder = holder;
        try {
            Log.i("SurfaceHolder", "setting preview");
            camera.setPreviewDisplay(mHolder);  
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder){
        Log.i("SurfaceHolder", "stopping preview");
        camera.stopPreview();
        mHolder = null;
    }
}
我的布局XML文件中的代码发布在下面

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_horizontal" >

    <ImageView
        android:id="@+id/photo"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:src="@drawable/b"
        android:scaleType="centerCrop"
        android:contentDescription="@string/happy" />

    <ToggleButton
        android:id="@+id/toggle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_margin="10dp"
        android:layout_marginBottom="17dp"
        android:background="@drawable/check"
        android:focusable="false"
        android:focusableInTouchMode="false" />

    <SurfaceView
        android:id="@+id/PREVIEW"
        android:layout_width="1dp"
        android:layout_height="1dp" />

</RelativeLayout>

导致问题的线路是

p.setFlashMode(Parameters.FLASH_MODE_OFF);
此时
p
为空。您可能认为您已经用初始化了它

final Parameters p = camera.getParameters();
onCreate()
方法中,但这是不正确的。此
p
onCreate()中声明并初始化,因此它是唯一可用的位置

private Parameters p;
上面的
p
是您的应用程序在
p.setFlashMode(Parameters.FLASH\u MODE\u OFF)行中使用的内容

要纠正这一点,只需改变

final Parameters p = camera.getParameters();

如果你真的需要它是最终的,你可以把这个关键字添加到你的列表顶部

private Parameters p;

由于应用程序崩溃,请按照上面链接的指导发布日志。@Andrew T。我刚刚发布了日志,因为这是
final Parameters p=camera.getParameters()代码。在顶部声明变量
p
,但从不初始化它。您只初始化在onCreate中声明的一个。当您使用
p.setFlashMode(Parameters.FLASH_MODE_OFF)时
p为空;好的,错误消失了。但是由于一些奇怪的原因,手电筒在实际设备上没有打开和关闭我对Android相关的硬件不是很熟悉,所以我可能无法帮你。抱歉,没问题。感谢您投票/接受了一个帮助您解决问题的答案。很多时候,人们得到了他们需要的帮助,然后就离开了。
p = camera.getParameters();
private Parameters p;