尝试打开闪光灯时,某些设备会崩溃

时间:2014-09-29 08:05:57

标签: android android-camera surfaceview crash-reports flashlight

我开发了一个可以打开LED闪光灯的Android应用程序。这似乎适用于大多数手机,但由于该应用程序可从Google Play下载,我在手电筒中收到一些崩溃报告。 我甚至得到了Nexus 5的报告,我有同样的手机,但我没有任何问题。这是我的代码:

private ImageButton mFlashButton;
private Parameters mParams;
private Camera mCamera;
private Thread t;
private ImageView ivRing;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.flashlight_fragment,
            container, false);

    ivRing = (ImageView) view.findViewById(R.id.ivRing);

    // flash switch button
    mFlashButton = (ImageButton) view.findViewById(R.id.flashlight_button);

    // Switch button click event to toggle flash on/off
    mFlashButton.setOnClickListener(mClickListener);

    return view;
}

View.OnClickListener mClickListener = new View.OnClickListener() {
    public void onClick(View v) {
        if (mLightOn) {
            turnOffFlash();
        } else {
            turnOnFlash();
        }
    }
};

@Override
public void onStart() {
    super.onStart();
    SurfaceView preview = (SurfaceView) getView().findViewById(R.id.PREVIEW);
    SurfaceHolder mHolder = preview.getHolder();
    mHolder.addCallback(this);
}

@Override
public void onPause() {
    super.onPause();
    turnOffFlash(true);
}

// Turning On flash
private void turnOnFlash() {

    if (!mLightOn) {
        //if camera not found, break
        if (mCamera == null || mParams == null) {
            Toast.makeText(getActivity(), "Error", Toast.LENGTH_SHORT).show();
        } else {
            mParams = mCamera.getParameters();
            mParams.setFlashMode(Parameters.FLASH_MODE_TORCH);
            mCamera.setParameters(mParams);
            mCamera.startPreview();
            mLightOn = true;
        }
    }

    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}


// Turning Off flash
private void turnOffFlash() {

    if (mLightOn) {
        //if camera is null, break;
        if (mCamera == null || mParams == null) {
            Toast.makeText(getActivity(), "Error", Toast.LENGTH_SHORT).show();
        } else {
            //strobo not running, just turn flash off
            mParams = mCamera.getParameters();
            mParams.setFlashMode(Parameters.FLASH_MODE_OFF);
            mCamera.setParameters(mParams);
            mCamera.stopPreview();
            mLightOn = false;
        }
        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }
}


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

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if (mCamera != null) {
        mCamera.stopPreview();
        mCamera.setPreviewCallback(null);
        mCamera.release();
        mCamera = null;
    }
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    if (mCamera == null) {
        //next line forced closed once, should look into this
        try {
            mCamera = Camera.open();
            mParams = mCamera.getParameters();
        } catch (Exception e) {
            Toast.makeText(getActivity(), "Something went wrong, please restart flashlight", Toast.LENGTH_SHORT).show();
        }
        try {
            mCamera.setPreviewDisplay(holder);
        } catch (Exception e) {
            mCamera.release();
            mCamera = null;
            Toast.makeText(getActivity(), "Something went wrong, please restart flashlight", Toast.LENGTH_SHORT).show();
        }
    }
}

}

这些是我得到的崩溃报告:

java.lang.RuntimeException: setParameters failed
at android.hardware.Camera.native_setParameters(Native Method)
at android.hardware.Camera.setParameters(Camera.java:1650)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)

此崩溃报告:

java.lang.NullPointerException: Attempt to invoke virtual method 'void     android.hardware.Camera.setPreviewDisplay(android.view.SurfaceHolder)' on a null object reference
at android.view.SurfaceView.updateWindow(SurfaceView.java:572)
at android.view.SurfaceView.access$000(SurfaceView.java:86)
at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:175)
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1867)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5600)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
at android.view.Choreographer.doCallbacks(Choreographer.java:574)
at android.view.Choreographer.doFrame(Choreographer.java:544)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)

有没有人有丝毫的线索在这里发生什么?事实上,它不会在我的Nexus 5上崩溃而在另一个上崩溃会让我感到困惑。

提前致谢

2 个答案:

答案 0 :(得分:1)

可能有些设备不支持闪存(可能是他们没有闪存)所以为此你首先要检查设备是否支持手电筒。

boolean hasFlash = getApplicationContext().getPackageManager()
        .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);

if (!hasFlash) {
    // device doesn't support flash
    // Show alert message and close the application
    AlertDialog alert = new AlertDialog.Builder(context)
            .create();
    alert.setTitle("Error");
    alert.setMessage("Sorry, your device doesn't support flash light!");
    alert.setButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            // closing the application or what ever you want if device does not support
            finish();
        }
    });
    alert.show();
    return;
}
else {
  //turn on flash light code here....
}

答案 1 :(得分:1)

    mCamera.setPreviewDisplay(holder);

失败了。您正在将NPE调用到另一个方法而不是在方法中处理NPE。