我正在开发一个Android
应用程序,用于自动从Front
和Back
相机捕获图像。我已经完成了将相机从后向前切换并保存捕获图像的编码进入SDcard
。我在手动点击按钮时测试捕获图像,效果很好。我需要的是从back camera
自动捕获图像然后从front camera
自动捕获图像出于这个目的,我使用了handler.postDelayed()
方法,但它显示了java.lang.RuntimeException: takePicture failed
。在这里我附上了我的代码,所以任何人都可以帮我解决错误。
MainActivity.java
package com.example.camera1;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private Camera cameraObject;
private ShowCamera showCamera;
private ImageView pic;
private Button takePhotoButton;
FrameLayout preview;
private static final ScheduledExecutorService worker =
Executors.newSingleThreadScheduledExecutor();
public static Camera isCameraAvailiable(){
Camera object = null;
try {
object = Camera.open();
}
catch (Exception e){
}
return object;
}
private PictureCallback capturedIt = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data .length);
if(bitmap==null){
Toast.makeText(getApplicationContext(), "not taken", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(), "taken", Toast.LENGTH_SHORT).show();
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d("", "Can't create directory to save image.");
Toast.makeText(MainActivity.this, "Can't create directory to save image.",
Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast.makeText(MainActivity.this, "New Image saved:" + photoFile,
Toast.LENGTH_LONG).show();
} catch (Exception error) {
Log.d("Constants.DEBUG_TAG", "File" + filename + "not saved: "
+ error.getMessage());
Toast.makeText(MainActivity.this, "Image could not be saved.",
Toast.LENGTH_LONG).show();
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
takePhotoButton = (Button)findViewById(R.id.button_takephoto);
cameraObject = isCameraAvailiable();
showCamera = new ShowCamera(this, cameraObject);
preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(showCamera);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
cameraObject.takePicture(null, null, capturedIt);
}
}, 5000);
cameraObject.stopPreview();
preview.removeView(showCamera);
cameraObject.release();
cameraObject = Camera.open(1);
showCamera = new ShowCamera(MainActivity.this, cameraObject);
preview.addView(showCamera);
Handler handlerFront = new Handler();
handlerFront.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
cameraObject.takePicture(null, null, capturedIt);
}
}, 5000);
}
private File getDir() {
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(sdDir, "Front&BackCamera");
}
@Override
public void onPause(){
super.onPause();
if (cameraObject != null) {
cameraObject.stopPreview();
cameraObject.release();
cameraObject = null;
}
// FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.removeView(showCamera);
}
@Override
public void onBackPressed() {
if (cameraObject != null) {
cameraObject.stopPreview();
cameraObject.release();
cameraObject = null;
}
finish();
return;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
ShowCamera.java
package com.example.camera1;
import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class ShowCamera extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holdMe;
private Camera theCamera;
public ShowCamera(Context context,Camera camera) {
super(context);
theCamera = camera;
holdMe = getHolder();
holdMe.addCallback(this);
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
theCamera.setDisplayOrientation(90);
theCamera.setPreviewDisplay(holder);
theCamera.startPreview();
} catch (IOException e) {
}
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
this.getHolder().removeCallback(this);
theCamera.stopPreview();
theCamera.release();
}
}
LogCat输出
05-30 15:22:07.102: E/AndroidRuntime(7629): FATAL EXCEPTION: main
05-30 15:22:07.102: E/AndroidRuntime(7629): java.lang.RuntimeException: takePicture failed
05-30 15:22:07.102: E/AndroidRuntime(7629): at android.hardware.Camera.native_takePicture(Native Method)
05-30 15:22:07.102: E/AndroidRuntime(7629): at android.hardware.Camera.takePicture(Camera.java:1233)
05-30 15:22:07.102: E/AndroidRuntime(7629): at android.hardware.Camera.takePicture(Camera.java:1178)
05-30 15:22:07.102: E/AndroidRuntime(7629): at com.example.camera1.MainActivity$2.run(MainActivity.java:176)
05-30 15:22:07.102: E/AndroidRuntime(7629): at android.os.Handler.handleCallback(Handler.java:615)
05-30 15:22:07.102: E/AndroidRuntime(7629): at android.os.Handler.dispatchMessage(Handler.java:92)
05-30 15:22:07.102: E/AndroidRuntime(7629): at android.os.Looper.loop(Looper.java:153)
05-30 15:22:07.102: E/AndroidRuntime(7629): at android.app.ActivityThread.main(ActivityThread.java:5086)
05-30 15:22:07.102: E/AndroidRuntime(7629): at java.lang.reflect.Method.invokeNative(Native Method)
05-30 15:22:07.102: E/AndroidRuntime(7629): at java.lang.reflect.Method.invoke(Method.java:511)
05-30 15:22:07.102: E/AndroidRuntime(7629): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
05-30 15:22:07.102: E/AndroidRuntime(7629): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
05-30 15:22:07.102: E/AndroidRuntime(7629): at dalvik.system.NativeStart.main(Native Method)
答案 0 :(得分:1)
您可以通过移动
轻松重写代码 cameraObject.stopPreview();
preview.removeView(showCamera);
cameraObject.release();
cameraObject = Camera.open(1);
showCamera = new ShowCamera(MainActivity.this, cameraObject);
preview.addView(showCamera);
Handler handlerFront = new Handler();
handlerFront.postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
cameraObject.takePicture(null, null, capturedIt);
}
}, 5000);
使用单独的方法,将其命名为MainActivity.takeSecondPictureAfterDelay()
。现在,在完成处理第一张图片的所有工作后,不要从MainActivity.OnCeate()
调用此方法,而是从onPictureTaken()
调用此方法。
要做的重要更改:您需要一些机制来检查此方法是否仅被调用一次。例如。添加
private int picturesTaken = 0;
并在onPictureTaken()
- 方法的最开头 - 添加
picturesTaken++;
if (picturesTaken >= 2) {
return;
}
现在你可以进行一些清理,例如没有必要使用Handler
来分隔。您可以为两张图片重复使用相同的处理程序,甚至可以使用showCamera.postDelayed()
代替handlerXXX.postDelayed()
。