我试图通过代码调用camera.takepicture,它总是抛出运行时异常。我似乎无法在我的代码中找到错误。如果我使用按钮调用相同的东西,那么拍摄图片就可以了。我需要通过代码调用takepicture,因为我需要它在用户实际执行不同活动时随机捕获照片。我需要设置一个计时器/间隔来查看这些照片。我不能依赖于这部分程序中的用户交互。
以下是有关详细信息的代码。另外还有logcat。
CameraActivity.class
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnClickListener;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class CameraActivity extends Activity implements Callback {
final static String DEBUG_TAG = "CameraActivity";
final static String TAG = "CameraActivity";
Camera camera;
private int cameraId = 0;
Button photo;
PhotoHandler mPhotoHandler = null;
Camera.Parameters parameters;
private SurfaceHolder sHolder;
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// do we have a camera?
if (!getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG)
.show();
} else {
cameraId = findFrontFacingCamera();
if (cameraId < 0) {
Toast.makeText(this, "No front facing camera found.",
Toast.LENGTH_LONG).show();
} else {
camera = Camera.open(cameraId);
SurfaceView sv = new SurfaceView(getApplicationContext());
setContentView(R.layout.camera);
sv = (SurfaceView) findViewById(R.id.surfaceview);
photo = (Button) findViewById(R.id.takepicture);
photo.setText("Click a photo!!");
// Get a surface
sHolder = sv.getHolder();
sHolder.addCallback(this);
sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
try {
camera.setPreviewDisplay(sHolder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
parameters = camera.getParameters();
// set camera parameters
camera.setParameters(parameters);
camera.startPreview();
camera.setDisplayOrientation(90);
try {
photo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
// Toast.makeText(getApplicationContext(),
// "photo clicked!",
// Toast.LENGTH_SHORT).show();
// just calling the function which captures the
// photo
takePhoto();
}
});
photo.performClick();
// finish();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// set any cam params you need...
camera.startPreview();
}
private int findFrontFacingCamera() {
int cameraId = -1;
// Search for the front facing camera
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
Log.d(DEBUG_TAG, "CameraActivity found");
cameraId = i;
break;
}
}
return cameraId;
}
@Override
protected void onPause() {
if (camera != null) {
camera.release();
camera = null;
}
super.onPause();
}
Camera.ShutterCallback shuttercallback = new Camera.ShutterCallback() {
@Override
public void onShutter() {
// TODO Auto-generated method stub
Log.d(TAG, "onShutter'd");
}
};
Camera.PictureCallback rawpicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
Log.d(TAG, "onPictureTaken - raw");
}
};
Camera.PictureCallback jpegcallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera arg1) {
// TODO Auto-generated method stub
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d(CameraActivity.DEBUG_TAG,
"Can't create directory to save image.");
Toast.makeText(CameraActivity.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(CameraActivity.this,
"New Image saved:" + photoFile, Toast.LENGTH_LONG)
.show();
} catch (Exception error) {
Log.d(CameraActivity.DEBUG_TAG, "File" + filename
+ "not saved: " + error.getMessage());
Toast.makeText(CameraActivity.this,
"Image could not be saved.", Toast.LENGTH_LONG).show();
}
}
};
@Override
public void surfaceCreated(SurfaceHolder holder) {
// set any cam params you need...
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera.stopPreview();
camera.release();
}
private static File getDir() {
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(sdDir, "CameraAPIDemo");
}
public void takePhoto() {
camera.takePicture(shuttercallback, rawpicture, jpegcallback);
}
}
附加是logcat输出
*
> 04-17 00:41:03.264: D/CameraActivity(19076): CameraActivity found
> 04-17 00:41:03.444: D/Camera(19076): app passed NULL surface 04-17
> 00:41:03.474: W/System.err(19076): java.lang.RuntimeException:
> takePicture failed 04-17 00:41:03.474: W/System.err(19076): at
> android.hardware.Camera.native_takePicture(Native Method) 04-17
> 00:41:03.474: W/System.err(19076): at
> android.hardware.Camera.takePicture(Camera.java:1095) 04-17
> 00:41:03.474: W/System.err(19076): at
> android.hardware.Camera.takePicture(Camera.java:1040) 04-17
> 00:41:03.474: W/System.err(19076): at
> com.egnoita.ignoramus.CameraActivity.takePhoto(CameraActivity.java:226)
> 04-17 00:41:03.474: W/System.err(19076): at
> com.egnoita.ignoramus.CameraActivity$4.onClick(CameraActivity.java:93)
> 04-17 00:41:03.474: W/System.err(19076): at
> android.view.View.performClick(View.java:4204) 04-17 00:41:03.484:
> W/System.err(19076): at
> com.egnoita.ignoramus.CameraActivity.onCreate(CameraActivity.java:96)
> 04-17 00:41:03.484: W/System.err(19076): at
> android.app.Activity.performCreate(Activity.java:5104) 04-17
> 00:41:03.484: W/System.err(19076): at
> android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
> 04-17 00:41:03.484: W/System.err(19076): at
> android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
> 04-17 00:41:03.484: W/System.err(19076): at
> android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
> 04-17 00:41:03.484: W/System.err(19076): at
> android.app.ActivityThread.access$600(ActivityThread.java:141) 04-17
> 00:41:03.484: W/System.err(19076): at
> android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
> 04-17 00:41:03.484: W/System.err(19076): at
> android.os.Handler.dispatchMessage(Handler.java:99) 04-17
> 00:41:03.484: W/System.err(19076): at
> android.os.Looper.loop(Looper.java:137) 04-17 00:41:03.484:
> W/System.err(19076): at
> android.app.ActivityThread.main(ActivityThread.java:5041) 04-17
> 00:41:03.484: W/System.err(19076): at
> java.lang.reflect.Method.invokeNative(Native Method) 04-17
> 00:41:03.484: W/System.err(19076): at
> java.lang.reflect.Method.invoke(Method.java:511) 04-17 00:41:03.484:
> W/System.err(19076): at
> com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
> 04-17 00:41:03.484: W/System.err(19076): at
> com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 04-17
> 00:41:03.484: W/System.err(19076): at
> dalvik.system.NativeStart.main(Native Method) 04-17 00:41:03.534:
> D/libEGL(19076): loaded /system/lib/egl/libEGL_adreno200.so 04-17
> 00:41:03.534: D/libEGL(19076): loaded
> /system/lib/egl/libGLESv1_CM_adreno200.so 04-17 00:41:03.544:
> D/libEGL(19076): loaded /system/lib/egl/libGLESv2_adreno200.so 04-17
> 00:41:03.554: I/Adreno200-EGL(19076): <eglInitialize:269>: EGL 1.4
> QUALCOMM build: Nondeterministic
> AU_full_mako_PARTNER-ANDROID/JB-MR1-DEV_CL2961380_release_AU
> (CL2961380) 04-17 00:41:03.554: I/Adreno200-EGL(19076): Build Date:
> 12/10/12 Mon 04-17 00:41:03.554: I/Adreno200-EGL(19076): Local Branch:
> 04-17 00:41:03.554: I/Adreno200-EGL(19076): Remote Branch:
> m/partner-android/jb-mr1-dev 04-17 00:41:03.554:
> I/Adreno200-EGL(19076): Local Patches: NONE 04-17 00:41:03.554:
> I/Adreno200-EGL(19076): Reconstruct Branch: NOTHING 04-17
> 00:41:03.624: D/OpenGLRenderer(19076): Enabling debug mode 0
* 如果您还需要更多信息,请与我们联系。 所有权限和功能都添加到清单
中<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_DATA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
答案 0 :(得分:1)
我遇到了同样的问题,为了解决这个问题,我简单地将takephoto定义为静态,将回调定义为静态。在这之后,我可以通过代码调用takephoto。
例如:
public static void takePhoto() {
camera.takePicture(shuttercallback, rawpicture, jpegcallback);
}
static Camera.PictureCallback jpegcallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera arg1) {
// TODO Auto-generated method stub
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d(CameraActivity.DEBUG_TAG,
"Can't create directory to save image.");
Toast.makeText(CameraActivity.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(CameraActivity.this,
"New Image saved:" + photoFile, Toast.LENGTH_LONG)
.show();
} catch (Exception error) {
Log.d(CameraActivity.DEBUG_TAG, "File" + filename
+ "not saved: " + error.getMessage());
Toast.makeText(CameraActivity.this,
"Image could not be saved.", Toast.LENGTH_LONG).show();
}
}
};
static Camera.ShutterCallback shuttercallback = new Camera.ShutterCallback() {
@Override
public void onShutter() {
// TODO Auto-generated method stub
Log.d(TAG, "onShutter'd");
}
};
static Camera.PictureCallback rawpicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
Log.d(TAG, "onPictureTaken - raw");
}
};
我希望这可以帮助您或其他任何有同样问题的人。
答案 1 :(得分:0)
您不需要进行巡视,以便从onClick()调用takePhoto()
。您的程序化方法失败的原因是camera.takePicture()只能在 camera.startPreview()完成后调用。这恰好是关于Android相机生命周期的common misunderstanding。
最重要的是,在onCreate()
中,您应该让活动准备好拍照,然后让所有必要的回调按顺序调用。这是对代码的最小重写。我希望它不仅可以完成这项工作,还可以帮助您了解正确对待相机的方法。
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnClickListener;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class CameraActivity extends Activity implements Callback {
final static String DEBUG_TAG = "CameraActivity";
final static String TAG = "CameraActivity";
Camera camera;
private int cameraId = 0;
Button photo;
PhotoHandler mPhotoHandler = null;
private boolean wantPhoto = false;
Camera.Parameters parameters;
private SurfaceHolder sHolder;
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// do we have a camera?
if (!getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG)
.show();
} else {
cameraId = findFrontFacingCamera();
if (cameraId < 0) {
Toast.makeText(this, "No front facing camera found.",
Toast.LENGTH_LONG).show();
} else {
camera = Camera.open(cameraId);
SurfaceView sv = new SurfaceView(getApplicationContext());
setContentView(R.layout.camera);
sv = (SurfaceView) findViewById(R.id.surfaceview);
photo = (Button) findViewById(R.id.takepicture);
photo.setText("Click a photo!!");
// Get a surface
sHolder = sv.getHolder();
sHolder.addCallback(this);
sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
try {
camera.setPreviewDisplay(sHolder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
parameters = camera.getParameters();
// set camera parameters
camera.setParameters(parameters);
camera.startPreview();
camera.setDisplayOrientation(90);
try {
photo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
// Toast.makeText(getApplicationContext(),
// "photo clicked!",
// Toast.LENGTH_SHORT).show();
// just calling the function which captures the
// photo
takePhoto();
}
});
// photo.performClick();
wantPhoto = true;
// finish();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// set any cam params you need...
camera.startPreview();
if (wantPhoto) {
wantPhoto = false;
takePhoto();
}
}
private int findFrontFacingCamera() {
int cameraId = -1;
// Search for the front facing camera
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
Log.d(DEBUG_TAG, "CameraActivity found");
cameraId = i;
break;
}
}
return cameraId;
}
@Override
protected void onPause() {
if (camera != null) {
camera.release();
camera = null;
}
super.onPause();
}
Camera.ShutterCallback shuttercallback = new Camera.ShutterCallback() {
@Override
public void onShutter() {
// TODO Auto-generated method stub
Log.d(TAG, "onShutter'd");
}
};
Camera.PictureCallback rawpicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
Log.d(TAG, "onPictureTaken - raw");
}
};
Camera.PictureCallback jpegcallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera arg1) {
// TODO Auto-generated method stub
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d(CameraActivity.DEBUG_TAG,
"Can't create directory to save image.");
Toast.makeText(CameraActivity.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(CameraActivity.this,
"New Image saved:" + photoFile, Toast.LENGTH_LONG)
.show();
} catch (Exception error) {
Log.d(CameraActivity.DEBUG_TAG, "File" + filename
+ "not saved: " + error.getMessage());
Toast.makeText(CameraActivity.this,
"Image could not be saved.", Toast.LENGTH_LONG).show();
}
}
};
@Override
public void surfaceCreated(SurfaceHolder holder) {
// set any cam params you need...
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera.stopPreview();
camera.release();
}
private static File getDir() {
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(sdDir, "CameraAPIDemo");
}
public void takePhoto() {
camera.takePicture(shuttercallback, rawpicture, jpegcallback);
}
}
请理解,有一些重要的改进可能会使您的代码受益。例如,建议在后台线程上调用camera.open(),因为在某些设备上,这可能是一个漫长的过程,并且可能会冻结UI超过一秒钟。