我的自定义相机实现适用于约95%的用户。 但是有些时候,当他们恢复相机预览活动后有一个NullPointerException,比如说从画廊中挑选照片(而不是拍摄实际照片),或者他们最小化应用程序,我不知道为什么,但即使相机实例在使用之前就已创建。
请查看我的代码(标记错误行如下:/ *第30行 - > * /)。
例外:
Android版本:android版本:4.4.4
这是我的自定义错误处理程序结果:java.lang.NullPointerException 在com.cerculdivelor.posting.CameraPreview。(CameraPreview.java:30)at com.cerculdivelor.posting.CameraActivity.startCameraPreview(CameraActivity.java:130) 在 com.cerculdivelor.posting.CameraActivity.onResume(CameraActivity.java:99) 在 android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1199) 在android.app.Activity.performResume(Activity.java:5521)at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3046) 在 android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3085) 在 android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1325) 在android.os.Handler.dispatchMessage(Handler.java:102)at android.os.Looper.loop(Looper.java:136)at android.app.ActivityThread.main(ActivityThread.java:5584)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:1268) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)at dalvik.system.NativeStart.main(原生方法)
相机活动:
@Override
protected void onResume() {
super.onResume();
//Start the camera preview
if (Build.VERSION.SDK_INT >= 23) {
checkCameraPermissionFirst();
} else {
try {
startCameraPreview();
} catch(Exception e){
http.sendToServer(e);
}
}
//Check write permission, prompt the user to grant permission in case if SDK > 19 (Lolipop)
if (Build.VERSION.SDK_INT >= 23) {
checkWritePermissionFirst();
}
}
@Override
protected void onPause() {
super.onPause();
Log.i("TAG", "PAUSED!!");
// TODO: kicsit veszelyes, figyelemmel kell kovetni!
//mCamera = null;
}
private void startCameraPreview() {
// Create an instance of Camera
mCamera = getCameraInstance();
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
// remove any inital previews
//TODO: ezt azert figyelni kell meg!
preview.removeAllViews();
/* line 130 -> */ mPreview = new CameraPreview(this, mCamera);
preview.addView(mPreview);
}
public static Camera getCameraInstance(Context context) {
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
} catch (Exception e) {
// Camera is not available (in use or does not exist)
Log.w("TAG", "Camera error: " + e);
HttpConActivity http = new HttpConActivity(context);
http.sendToServer(e);
}
return c; // returns null if camera is unavailable
}
相机预览活动:
package com.cerculdivelor.posting;
import java.io.IOException;
import java.util.List;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private Context mContext;
private SurfaceHolder mHolder;
private Camera mCamera;
private List<Size> mSupportedPreviewSizes;
private Size mPreviewSize;
public CameraPreview(Context context, Camera camera) {
super(context);
mContext = context;
mCamera = camera;
// supported preview sizes
/* line 30 -> */ mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
for(Size str: mSupportedPreviewSizes)
Log.e(TAG, "Preview sizes available: " + str.width + "/" + str.height);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// empty. surfaceChanged will take care of stuff
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
Log.i("TAG", "Surface was distroyed.");
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged => w=" + w + ", h=" + h);
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or reformatting changes here
// start preview with new settings
if(mCamera != null) {
try {
Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
if (parameters.getSupportedFocusModes().contains(
Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
float ratio;
if(mPreviewSize.height >= mPreviewSize.width)
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
else
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
// One of these methods should be used, second method squishes preview slightly
setMeasuredDimension(width, (int) (width * ratio));
// setMeasuredDimension((int) (width * ratio), height);
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Size size : sizes) {
double ratio = (double) size.height / size.width;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}
答案 0 :(得分:0)
这可能是因为当应用程序在后台被销毁时mCamera正在丢失。你试过把相机实例放在课堂上吗?
mCamera = camera;
if(mCamera==null)
{
mCamera = getCameraInstance()
}
答案 1 :(得分:0)
在你的surfaceDestroyed中你将相机设置为null(mCamera = null;),然后当你的应用程序再次出现时,你的变量为null,请尝试使用surfaceCreated方法:
if (mCamera == null) {
mCamera = Camera.open();
mCamera.setPreviewDisplay(holder);
}