在sdk中找到/sdk/docs/guide/topics/media/camera.html#custom-camera,里面有详细的api参考
在清单文件中添加相应的权限:
XML/HTML代码
按照官方文档,分为下面几步:
• Detect and Access Camera - Create code to check for the existence of cameras and request access.
• Create a Preview Class - Create a camera preview class that extends SurfaceView and implements theSurfaceHolder interface. This class previews the live images from the camera.
• Build a Preview Layout - Once you have the camera preview class, create a view layout that incorporates the preview and the user interface controls you want.
• Setup Listeners for Capture - Connect listeners for your interface controls to start image or video capture in response to user actions, such as pressing a button.
• Capture and Save Files - Setup the code for capturing pictures or videos and saving the output.
• Release the Camera - After using the camera, your application must properly release it for use by other applications.
接下来分别实现:
1、检查设备是否有照相机
Java代码/** 检查设备是否存在照相机 */
privatebooleancheckCameraHardware(Context context) {
if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
returntrue;
} else{
// no camera on this device
returnfalse;
}
}
2、得到一个照相机
Java代码/** 一种安全的方式获取Cameer对象的实例. */
publicstaticCamera 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)
}
returnc;// returns null if camera is unavailable
}
3、新建一个名为CameraPreview的类
Java代码packagecom.wuyudong.mycamera;
importjava.io.IOException;
importandroid.content.Context;
importandroid.hardware.Camera;
importandroid.util.Log;
importandroid.view.SurfaceHolder;
importandroid.view.SurfaceView;
/** A basic Camera preview class */
publicclassCameraPreviewextendsSurfaceViewimplements
SurfaceHolder.Callback {
privatestaticfinalString TAG ="CameraPreview";
privateSurfaceHolder mHolder;
privateCamera mCamera;
publicCameraPreview(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);
}
publicvoidsurfaceCreated(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());
}
}
publicvoidsurfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
publicvoidsurfaceChanged(SurfaceHolder holder,intformat,intw,inth) {
// 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());
}
}
}
4、设置一个预览功能的layout,将原来布局文件中的内容替换成下面的代码
XML/HTML代码<?xmlversion ="1.0"encoding="utf-8"?>
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
android:id="@+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
5、在清单文件中加入 android:screenOrientation="landscape" 调整相机为横向拍摄
6、在MainActivity中添加
Java代码publicclassMainActivityextendsActivity {
privateCamera mCamera;
privateCameraPreview mPreview;
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
mPreview = newCameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
}
7、实现拍摄按钮的功能
(1)添加拍照回调方法
Java代码privatePictureCallback mPicture =newPictureCallback() {
@Override
publicvoidonPictureTaken(byte[] data, Camera camera) {
File pictureFile = newFile("/sdcard/"+ System.currentTimeMillis()+".jpg");
try{
FileOutputStream fos = newFileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch(IOException e) {
Log.d("TAG","Error accessing file: "+ e.getMessage());
}
}
};
给拍照按钮添加注册事件:
Java代码// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
newView.OnClickListener() {
@Override
publicvoidonClick(View v) {
// get an image from the camera
mCamera.takePicture(null,null, mPicture);
}
}
);
完整的代码如下:
Java代码packagecom.wuyudong.mycamera;
importjava.io.File;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.sql.Date;
importandroid.os.Bundle;
importandroid.app.Activity;
importandroid.content.Context;
importandroid.content.pm.PackageManager;
importandroid.hardware.Camera;
importandroid.hardware.Camera.AutoFocusCallback;
importandroid.hardware.Camera.PictureCallback;
importandroid.util.Log;
importandroid.view.Menu;
importandroid.view.View;
importandroid.widget.Button;
importandroid.widget.FrameLayout;
publicclassMainActivityextendsActivity {
privateCamera mCamera;
privateCameraPreview mPreview;
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建一个 Camera 的实例
mCamera = getCameraInstance();
// 创建一个预览界面
mPreview = newCameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
newView.OnClickListener() {
@Override
publicvoidonClick(View v) {
mCamera.autoFocus(newAutoFocusCallback() {// 对焦
@Override
publicvoidonAutoFocus(booleansuccess, Camera camera) {
// get an image from the camera
mCamera.takePicture(null,null, mPicture);
}
});
}
}
);
}
/** 检查设备是否存在照相机 */
privatebooleancheckCameraHardware(Context context) {
if(context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
// this device has a camera
returntrue;
} else{
// no camera on this device
returnfalse;
}
}
/** 一种安全的方式获取Cameer对象的实例. */
publicstaticCamera 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)
}
returnc;// returns null if camera is unavailable
}
privatePictureCallback mPicture =newPictureCallback() {
@Override
publicvoidonPictureTaken(byte[] data, Camera camera) {
File pictureFile = newFile("/sdcard/"+ System.currentTimeMillis()+".jpg");
try{
FileOutputStream fos = newFileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch(IOException e) {
Log.d("TAG","Error accessing file: "+ e.getMessage());
}
}
};
protectedvoidonDestory() {
if(mCamera !=null) {//释放资源
mCamera.release();
mCamera = null;
}
}
}
2016年9月9日