这是使用Fragment在Android Studio开发相机应用系列文章5篇中的第4篇。如果你没有读过之前的文章,先从GitHub上复制一份我的工程,这篇教程主要讨论”NativeCameraFragment“。
作者语:由于设备厂商庞多繁杂,不同版本相机API不同,一个完整健壮的相机应用是很复杂的。如果你想实现一个完整可行的,可以考虑以CWAC Camera为基础进行开发。我的目标仅仅是演示相机开发的一些基础。
除了安卓的原生相机应用,你也可以在自己的项目中使用相机功能。这涉及到直接利用安卓相机接口并把结果投射到“预览”界面或者SurfaceView上。
开启相机
一旦Fragment视图对象被创建,首先做的就是把相机和相机预览界面关联起来。你可以在谷歌的开发者网站上阅读相关的文档,下面是一个参考实现:
1
2
3
4
5
6
7
8
9
10
|
private boolean safeCameraOpenInView(View view) {
boolean qOpened = false ;
releaseCameraAndPreview();
mCamera = getCameraInstance();
qOpened = (mCamera != null );
mPreview = new CameraPreview(getActivity().getBaseContext(), mCamera);
FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_preview);
preview.addView(mPreview);
return qOpened;
}
|
该函数用来获取一个相机的实例对象并和我们的CameraPreview对象关联起来。
相机预览界面
例子中的CameraPreview 对象继承了SurfaceView 并实现了SurfaceHolder.callback接口,预览界面将显示相机的输入。在你看到正在拍摄的画面的同时,它将处理SurfaceHolder的生命周期:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
/**
* Surface on which the camera projects it's capture results.
*/
class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super (context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback( this );
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null ){
return ;
}
try {
mCamera.stopPreview();
} catch (Exception e){
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
e.printStackTrace();
}
}
}
|
相机拍照回调
Camera.PictureCallback是安卓用来判断何时相机拍摄了照片,并且获取了输出结果的回调接口。在我的示例项目工程中实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken( byte [] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null ){
Toast.makeText(getActivity(), "Image retrieval failed." , Toast.LENGTH_SHORT)
.show();
return ;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
|
免责声明和补充
文章一发布我就从安卓相机跨设备开发专家那得到了反馈,我的目标是提供高质量的内容,所以不说清楚下面的这些问题文章就不完整 。
在我的例子中假定设备支持jpeg格式,这种假定存在风险,真实的实现需要检查是否支持jpeg格式。另一个问题 CameraHolder.PreviewCallback接口直到API版本18许多厂商才支持,这使得API 18以前PreviewCallback 将难以起作用。
此例中,我使用的默认CameraPreview 格式是NV21,已经有人推荐我使用YV12(从API 12开始支持),一定要检查下相机支持的CameraPreview格式。实现格式因设备厂商不同而不同,是不一致行为的潜在根源。
还有包括闪光灯和聚焦模式在内的很多细节问题没有探讨,这些可能需要设置一些相机的参数,我已经在GitHub上更新了代码。
以上就是我直接使用安卓原生相机的例子,随便获取例子代码,同样,如果你觉得这篇文章对你有帮助欢迎分享。非常感谢。
原文链接: airpair 翻译: 伯乐在线 - 黄瓜
译文链接: http://blog.jobbole.com/72858/ |