我必须创建一个在后台捕获图片的android应用程序。我有代码,但它总是在某一时刻崩溃。这段代码在HTC android手机上运行良好。我在摩托罗拉,nexus及其崩溃时都尝试过它。
这是崩溃:
Process: com.capturepicture, PID: 13016
java.lang.RuntimeException: takePicture failed
at android.hardware.Camera.native_takePicture(Native Method)
at android.hardware.Camera.takePicture(Camera.java:1436)
at android.hardware.Camera.takePicture(Camera.java:1381)
at com.trimble.applanix.flightplanning.FlightPlanner.takepic(FlightPlanner.java:142)
at com.trimble.applanix.flightplanning.FlightPlanner$2.onClick(FlightPlanner.java:96)
at android.view.View.performClick(View.java:4761)
at android.view.View$PerformClick.run(View.java:19767)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
这是我的活动文件,它触发了摄像头代码
public class Planner extends Activity {
private Button btnStart;
private Button btnStop;
protected static Handler mHandler = null;
protected String mHttpResponse = "";
private int mHandlerWhatMessage;
Camera camera;
SurfaceView preview;
SurfaceHolder previewHolder;
ImageButton takePic;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flight_planner);
btnStart = (Button) findViewById(R.id.btn_start);
btnStop = (Button) findViewById(R.id.btn_stop);
preview = (SurfaceView) findViewById(R.id.surfaceView);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
takepic();
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
public void takepic(){
if (camera == null)
camera = Camera.open();
camera.cancelAutoFocus();
camera.startPreview();
System.gc();
camera.setPreviewCallback(null);
camera.takePicture(null, null, photoCallback);
camera.startPreview();
//camera.takePicture(ShutterCallback, rawCallback, photoCallback);
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters) {
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) {
result = size;
}
}
}
}
return (result);
}
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try {
camera.setPreviewDisplay(previewHolder);
} catch (Throwable t) {
Toast toast = Toast.makeText(FlightPlanner.this,
"Exception in setPreviewDisplay", Toast.LENGTH_LONG);
toast.show();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size bestSize = getBestPreviewSize(width, height, parameters);
parameters.setPreviewSize(bestSize.width, bestSize.height);
parameters.setPictureFormat(PixelFormat.JPEG);
camera.setParameters(parameters);
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
};
/*
Camera.ShutterCallback ShutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
}
};
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
}
};
*/
Camera.PictureCallback photoCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
// Save the image JPEG data to the SD card
FileOutputStream outStream = null;
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
Date now = new Date();
String fileName = formatter.format(now) +".jpg";
//String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/FLIGHTPLANNER");
myDir.mkdirs();
File file = new File (myDir, fileName);
if (file.exists ()) file.delete ();
outStream = new FileOutputStream(file);
outStream.write(data);
outStream.close();
} catch (FileNotFoundException e) {
Log.d("CAMERA", e.getMessage());
} catch (IOException e) {
Log.d("CAMERA", e.getMessage());
}
camera.startPreview();
/*new SavePhotoTask().execute(data);
camera.startPreview();*/
}
};
}
我在清单文件中添加了必需的相机权限。
答案 0 :(得分:1)
您必须先调用startPreview(),然后才能调用takePicture()。但是在调用startPreview()之后立即调用takePicture()是不正确的。它可能适用于某些设备,但不适用于其他设备。
一旦打开相机(当布局管理器创建SurfaceView时),最佳解决方案将开始预览。
但如果你不能接受,
preview.postDelayed(…, 300)
就足够了(参见类似的例子on GitHub)