目前的智能手机大都已支持照相机应用,在安卓开发中也经常会用到照相机这一模块,那么该如何调用这一模块呢?
一般有两种方法,不过也是根据具体需要来定,如果只是调用照相机应用,不涉及其他操作,建议直接调用系统原生照相机,如果希望个性化定制照相机应用,则需要自己设计显示框、相机参数和功能操作等。
1、调用系统原生照相机:
可以在源代码中定义一个调用相机的方法,并在方法中加入如下语句:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra("camerasensortype", 2); // 调用前置摄像头,不同屏可能参数不同
intent.putExtra("autofocus", false); // 是否自动对焦
intent.putExtra("fullScreen", false); // 是否全屏
intent.putExtra("showActionIcons", false); //是否显示活动图标
startActivityForResult(intent, PICK_FROM_CAMERA);//启动照相机应用
2、自定义照相机:
首先要创建一个相机类:CameraDialog.java
package com.android.xxx;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import com.android.xxx.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
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.os.PowerManager;
import android.view.Display;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
public class CameraDialog extends Activity {
SurfaceView sView;
SurfaceHolder surfaceHolder;
int screenWidth, screenHeight;
// 定义系统所用的照相机
public static Camera camera = null;
public static CameraDialog instance = null;
// 是否在浏览中
boolean isPreview = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// 设置全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.camera_dialog1);
instance = this;
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
// 获取屏幕的宽和高
screenWidth = display.getWidth();
screenHeight = display.getHeight();
// 获取界面中SurfaceView组件
sView = (SurfaceView) findViewById(R.id.sView);
// 获得SurfaceView的SurfaceHolder
surfaceHolder = sView.getHolder();
// 为surfaceHolder添加一个回调监听器
surfaceHolder.addCallback(new Callback() {
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
// 打开摄像头
initCamera();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// 如果camera不为null ,释放摄像头
if (camera != null) {
if (isPreview)
camera.stopPreview();
camera.release();
camera = null;
}
}
});
// 设置该SurfaceView自己不维护缓冲
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// MyTag可以随便写,可以写应用名称等
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
// 换成PowerManager.SCREEN_DIM_WAKE_LOCK会变暗)
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "MyTest1");
wl.acquire();// 开启屏幕常亮
}
private void initCamera() {
if (!isPreview) {
camera = Camera.open(0);//指定要打开的摄像头0为后置,1为前置
}
if (camera != null && !isPreview) {
try {
Camera.Parameters parameters = camera.getParameters();
// 设置预览照片的大小
// 设置显示图像旋转90度
if (Integer.parseInt(Build.VERSION.SDK) >= 8) {
setDisplayOrientation(camera, 90);
} else {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
parameters.set("orientation", "portrait");
parameters.set("rotation", 90);
}
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
parameters.set("orientation", "landscape");
parameters.set("rotation", 90);
}
}
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, 0, 0);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);//可根据优选方法设定预览分辨率,默认全屏显示
// parameters.setPreviewSize(screenWidth, screenHeight);//可设置指定的预览分辨率(一般只支持:176x144,320x240,352x288,480x360,640x480这几个分辨率,可根据实际情况来选)
// 每秒显示4帧
parameters.setPreviewFrameRate(5);
// 设置图片格式
parameters.setPictureFormat(PixelFormat.JPEG);
// 设置JPG照片的质量
parameters.set("jpeg-quality", 85);
// 设置照片的大小
// parameters.setPictureSize(3264, 2448);//根据相机本身支持的分辨率大小
// parameters.setPictureSize(optimalSize.width,optimalSize.height);//如果不清楚分辨率大小,可调用优选方法自动指定一个分辨率
// parameters.setPictureSize(screenWidth, screenHeight);
camera.setParameters(parameters);
// 通过SurfaceView显示取景画面
camera.setPreviewDisplay(surfaceHolder);
// 开始预览
camera.startPreview();
// 自动对焦
camera.autoFocus(null);
} catch (Exception e) {
e.printStackTrace();
}
isPreview = true;
}
}
public void setDisplayOrientation(Camera camera, int angle) {
Method downPolymorphic;
try {
downPolymorphic = camera.getClass().getMethod(
"setDisplayOrientation", new Class[] { int.class });
if (downPolymorphic != null)
downPolymorphic.invoke(camera, new Object[] { angle });
} catch (Exception e1) {
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
// 当用户单击照相键、中央键时执行拍照
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_CAMERA:
if (camera != null && event.getRepeatCount() == 0) {
// 拍照
camera.takePicture(null, null, myjpegCallback);
return true;
}
break;
}
return super.onKeyDown(keyCode, event);
}
PictureCallback myjpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
// 根据拍照所得的数据创建位图
final Bitmap bm = BitmapFactory.decodeByteArray(data, 0,
data.length);
// 加载/layout/save.xml文件对应的布局资源
View saveDialog = getLayoutInflater().inflate(R.layout.save, null);
final EditText photoName = (EditText) saveDialog
.findViewById(R.id.phone_name);
// 获取saveDialog对话框上的ImageView组件
ImageView show = (ImageView) saveDialog.findViewById(R.id.show);
// 显示刚刚拍得的照片
show.setImageBitmap(bm);
// 使用对话框显示saveDialog组件
new AlertDialog.Builder(CameraDialog1.this).setView(saveDialog)
.setPositiveButton("保存", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 创建一个位于SD卡上的文件
File file = new File(Environment
.getExternalStorageDirectory(), photoName
.getText().toString() + ".jpg");
FileOutputStream outStream = null;
try {
// 打开指定文件对应的输出流
outStream = new FileOutputStream(file);
// 把位图输出到指定文件中
bm.compress(CompressFormat.JPEG, 100, outStream);
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).setNegativeButton("取消", null).show();
// 重新浏览
camera.stopPreview();
camera.startPreview();
isPreview = true;
}
};
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h)//分辨率尺寸优选方法
{
final double ASPECT_TOLERANCE = 0.05;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
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;
}
}
其次,在主类中创建调用方法,并在其中添加如下两句:
Intent intent = new Intent(MainActivity.this, CameraDialog.class);
startActivity(intent);
在适当的时候调用该方法即可。
最后,注意在AndroidManifest.xml中添加相关权限配置:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android:hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
至此,自定义的照相机应用便设计出来了,它包含预览、自动对焦、拍照和照片存储功能。