App如何试图使用camera硬件特性的?
-在manifest中声明使用camera权限
-快速拍照还是自定义Camera?如果只是拍照或拍视频,使用现有的Camera App即可,否则要自定义Camera了。
-存储。产生的图片或视频打算只对你的应用可用还是可被其他应用(如Gallery或其他媒体库)共享?在App卸载时是否仍可用?
几个关键类:Camera,SurfaceView,MediaRecorder,Intent
Camera App:
-检测&访问Camera,用代码监测camera的存在并请求访问。
// Check if this device has a camera
private boolean checkCameraHardware(Context context) {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
private static Camera getCameraInstance() {
Camera camera = null;
try {
camera = Camera.open();
} catch (Exception e) {
// Camero is not available (in use or does not exist)
}
return camera;
}
-创建Preview类,创建一个继承自SurfaceView的Preview类,实现SurfaceHolder接口。这个类预览实时的图片和camera。
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = SurfaceView.class.getSimpleName();
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);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public CameraPreview(Context context, AttributeSet attrs) {
super(context, attires);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview " + e.getMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) { }
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview " + e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// releasing
}
}
-构建一个Preview布局。
略。
-设置捕获监听,对用户动作连接一个监听器,来控制开始拍照/拍摄
mHolder.addCallback(Callback c);
-捕获&保存文件。
构建完一个Preview类,将它置入一个layout之后,你就做好了捕获图像的准备。为了以JPEG格式接收数据,必需实现一个Camera.PictureCallback接口以接收图像数据,再写入文件。
图像文件/视频文件
(1)捕获图像
比较简单,主要是一个捕获图像后的回调。
mCamera.takePicture(null, null, mPicture);
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
Log.d(TAG, "Error creating media file, check storage permisions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
在onPictureTaken()回调方法里,把字节数组写进文件输出流里即可。
(2)捕获视频
主要是捕获视频的准备工作:
private boolean prepareVideoRecorder(){
mCamera = getCameraInstance();
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// Step 4: Set output file
mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
// Step 5: Set the preview output
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
// Step 6: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
完了之后就可以调mMediaRecorder.start()了。
但是存在一个让我疑惑的地方,录制的视频是如何写进视频文件的呢?我还没找到代码在哪。
-释放Camera。
略。
注:Camera是共享的资源,必需管理好对camera的使用。
这篇文章有点水了,这是官方training里面的一篇,我只是简单翻译了一下。
https://developer.android.com/guide/topics/media/camera.html#saving-media