我正在使用表面视图向用户显示相机预览。这是我启动它的方法:
private void pickCam(){
if (Camera.getNumberOfCameras() < 1)
return;
if (Camera.getNumberOfCameras() == 1)
{
CameraInfo cInfo=new CameraInfo();
Camera.getCameraInfo(0, cInfo);
camera = Camera.open(0);
}
else
camera = Camera.open(currentCamera);
Camera.Parameters parameters = camera.getParameters();
parameters = camera.getParameters();
parameters.setRotation(90);
try {
Camera.Size mCameraSize = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= surfaceWidth && size.height <= surfaceHeight) {
if (mCameraSize == null)
mCameraSize = size;
else {
int currentArea = mCameraSize.width
* mCameraSize.height;
int newArea = size.width * size.height;
if (newArea > currentArea) {
mCameraSize = size;
}
}
}
}
parameters.setPreviewSize(mCameraSize.width, mCameraSize.height);
camera.setParameters(parameters);
camera.setDisplayOrientation(90);
camera.setPreviewDisplay(surfaceHolder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();
}
当用户点击按钮时:
if (camera != null)
camera.takePicture(null, null,this);
此代码适用于Sony Xperia(2个摄像头),但HTC Wildfire和三星Galaxy S +(均为1个摄像头)的预览失败。没有例外,它只是显示没有。我可以在所有这些设备上拍照。
两个设备的pickCamMethod的LogCat输出为空:
04-23 14:25:22.987: I/System.out(5871): PickCamBegin
04-23 14:25:23.428: I/System.out(5871): PickCamEnd
我怎样才能让它在所有情况下都有效?
答案 0 :(得分:2)
在清单文件中添加权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
开发者网站有关于该主题的优秀文档。
http://developer.android.com/guide/topics/media/camera.html
我在开发者网站上使用了代码并制作了一个示例。根据您的需要修改以下内容。
在您的活动中
public class MainActivity extends Activity {
private static final int REQUEST_CODE = 1;
ImageView imageView;
Button b;
private Camera mCamera;
private CameraPreview mPreview;
private Bitmap bitmap;
private PictureCallback mPicture;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
boolean check =checkCameraHardware(MainActivity.this);
if(check)
{
mCamera = getCameraInstance();
// mCamera.setDisplayOrientation(90);
setCameraDisplayOrientation(this,
1, mCamera);//requires min sdk 9
}
// Create an instance of Camera
mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "MyImages");
if(!imagesFolder.exists())
imagesFolder.mkdirs();
File pictureFile = new File(imagesFolder, "image.jpg");
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
System.out.println("hello");
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d("No File", "File not found: " + e.getMessage());
} catch (IOException e) {
//Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
b = (Button) findViewById(R.id.button_capture);
b.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
mCamera.takePicture(null, null, mPicture);
Toast.makeText(MainActivity.this, "Called",1000).show();
}
});
}
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
Toast.makeText(this, "Phone has camera", Toast.LENGTH_LONG).show();
return true;
} else {
// no camera on this device
Toast.makeText(this, "Phone has no camera", Toast.LENGTH_LONG).show();
return false;
}
}
public static Camera getCameraInstance(){
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)
}
return c; // returns null if camera is unavailable
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
mCamera.release();
}
}
用于预览的CameraPreview类
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// 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) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int 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
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
activity_main.xml中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<Button
android:id="@+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
答案 1 :(得分:1)
正如您所提到的那些设备HTC Wildfire和Samsung Galaxy S +可能运行在不支持Camera.getNumberOfCameras()
的较低版本的Android上。
HTC Wildfire于2010年宣布,支持Android 2.2(API Lv.8)
Samsung Galaxy S+,支持Android 2.3(API Lv.9 / Lv.10)
可在此处找到API级别指南:Android Developers: What is API Level?
因此,您使用的方法Camera.getNumberOfCameras()
已添加到API 9中(请参阅Documentation)
您可能需要使用Build.VERSION
单独处理它们,因此您可以尝试更改pickCam()
的第一行:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
// Means the device is using API Lv.9+
// Use the method that can work for Lv.9+
if (Camera.getNumberOfCameras() < 1)
return;
if (Camera.getNumberOfCameras() == 1)
{
CameraInfo cInfo=new CameraInfo();
Camera.getCameraInfo(0, cInfo);
camera = Camera.open(0);
}
else
camera = Camera.open(currentCamera);
} else {
// Use alternative method that support lower API levels
camera = Camera.open();
}
Camera.open()
是适用于2.2的方法,Camera.open(int)
适用于2.3+(请参阅Documentation)
如果这对你有用,请告诉我。