【问题标题】:Crashes on some devices when trying to turn on flash尝试打开闪光灯时在某些设备上崩溃
【发布时间】:2014-09-29 08:05:57
【问题描述】:

我开发了一个可以打开 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 上崩溃并在另一个上崩溃的事实让我感到困惑..

提前致谢

【问题讨论】:

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


    【解决方案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....
    }
    

    【讨论】:

    • 感谢您的回复,但我已经检查过了。此代码仅适用于带 LED 闪光灯的设备。
    【解决方案2】:
        mCamera.setPreviewDisplay(holder);
    

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

    【讨论】:

    • surfaceCreated 作为一个函数真的很奇怪,如果 camera == null,你试试那些参数。其中之一是传递 holder,它也是 0。由于我不知道 setPreviewDisplay 实际上是什么,我建议您查看该部分。
    • 我相信在活动开始时会调用surfaceCreated,因此如果此时相机为空,我必须使用Camera.open() 对其进行实例化。持有人应该在 onStart() 中实例化,但我真的不知道为什么有时会失败。以我的经验,它每次都有效。顺便感谢您的意见!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-14
    相关资源
    最近更新 更多