Android实例讲解自定义Camera拍照和预览以及前后置摄像头切换

本博文将通过实例实现自定义Camera的功效。具体功能如下:

1.实现自定义Camera拍照;

2.实现前后置摄像头的切换;

3.实现Camera拍照后图片缩小显示以及正常预览;

4.实现Camera拍照后图片保存;

在具体实现代码之前,我们先来了解一下Android api对实现自定义Camera的介绍。

Android实例讲解自定义Camera拍照和预览以及前后置摄像头切换_第1张图片

根据api的介绍,对于Camera应用可以简单总结以下几个步骤。

1.检查Camera是否存在,并在AndroidManifest.xml中赋予相关的权限;

2.创建一个继承于SurfaceView并实现SurfaceHolder接口的Camera Preview类;

3.在2的基础上新建一个Camera Preview布局文件;

4.设置一个拍照的监听事件,例如单击按钮事件等;

5.实现拍照,并保存拍照后的图片到设备;

6.释放Camera,以方便其他应用可以使用。

下面将通过具体代码实现我们给出的三个功能。

一.相关的xml文件

1.AndroidManifest.xml相关配置以及相关权限,实现步骤一当中的权限配置

 

view source print ?
01. "1.0" encoding="utf-8"?>
02. "http://schemas.android.com/apk/res/android"
03. package="com.example.camerasurfacedemo"
04. android:versionCode="1"
05. android:versionName="1.0" >
06.  
07.
08. android:minSdkVersion="11"
09. android:targetSdkVersion="19" />
10.  
11. "android.permission.CAMERA" />
12. "android.permission.WRITE_EXTERNAL_STORAGE" />
13.  
14. "android.hardware.camera" />
15.  
16.
17. android:allowBackup="true"
18. android:icon="@drawable/ic_launcher"
19. android:label="@string/app_name"
20. android:theme="@style/AppTheme" >
21.
22. android:name="com.example.camerasurfacedemo.MainActivity"
23. android:label="@string/app_name" >
24.
25. "android.intent.action.MAIN" />
26.  
27. "android.intent.category.LAUNCHER" />
28.
29.
30.  
31. "com.example.camerasurfacedemo.CameraActivity"
32. >
33. "com.example.camerasurfacedemo.PreviewActivity"
34. >
35.
36.  
37.

2.activity_main.xml主函数入口,进入自定义Camera界面入口,实现拍照后图片缩小显示功能

 

 

view source print ?
01. "http://schemas.android.com/apk/res/android"
02. xmlns:tools="http://schemas.android.com/tools"
03. android:layout_width="match_parent"
04. android:layout_height="match_parent"
05. android:gravity="center_horizontal"
06. android:orientation="vertical" >
07. "
08.  
09.
10. android:id="@+id/id_go_camera_btn"
11. android:layout_width="match_parent"
12. android:layout_height="wrap_content"
13. android:gravity="center"
14. android:text="进入拍照界面" />
15.  
16.
17. android:id="@+id/id_show_camera_iv"
18. android:layout_width="150dp"
19. android:layout_height="200dp"
20. android:gravity="center" />
21.  
22.
23. android:layout_width="match_parent"
24. android:layout_height="match_parent"
25. android:gravity="center"
26. android:text="拍照图片显示区域"
27. android:textColor="#FF0000"
28. android:textSize="20sp" />
29.  
30.

3.activity_camera.xml自定义Camera preview布局,实现步骤2,该界面实现前后置摄像头切换以及自定义拍照等

 

 

view source print ?
01. "http://schemas.android.com/apk/res/android"
02. xmlns:tools="http://schemas.android.com/tools"
03. android:layout_width="match_parent"
04. android:layout_height="match_parent"
05. >
06.
07. android:id="@+id/id_process_btns_ll"
08. android:layout_width="match_parent"
09. android:layout_height="wrap_content"
10. android:orientation="horizontal"
11. android:layout_alignParentTop="true"
12. >
13.
14. android:id="@+id/id_switch_camera_btn"
15. android:layout_width="wrap_content"
16. android:layout_height="wrap_content"
17. android:layout_weight="1"
18. android:gravity="center"
19. android:text="切换前后摄像头"
20. />
21.
22. android:id="@+id/id_capture_btn"
23. android:layout_width="wrap_content"
24. android:layout_height="wrap_content"
25. android:layout_weight="1"
26. android:gravity="center"
27. android:text="拍照"
28. />
29.
30.
31. android:id="@+id/id_area_sv"
32. android:layout_width="match_parent"
33. android:layout_height="match_parent"
34. android:layout_below="@id/id_process_btns_ll"
35. android:text="拍照区域" />
36.  
37.
4.activity_preview.xml实现拍照后图片放大预览

 

 

view source print ?
01. "http://schemas.android.com/apk/res/android"
02. xmlns:tools="http://schemas.android.com/tools"
03. android:layout_width="match_parent"
04. android:layout_height="match_parent"
05. android:background="#000000"
06. android:orientation="vertical" >
07.  
08.
09. android:layout_width="match_parent"
10. android:layout_height="wrap_content"
11. android:gravity="center"
12. android:text="拍照图片预览"
13. android:textColor="#FF0000"
14. android:textSize="20sp"
15. />
16.  
17.
18. android:id="@+id/id_preview_camera_iv"
19. android:layout_width="wrap_content"
20. android:layout_height="wrap_content"
21. android:gravity="center" />
22.  
23.

二.java代码实现

 

1.帮助类HelpUtil.java

 

view source print ?
01. package com.example.camerasurfacedemo;
02.  
03. import java.io.FileInputStream;
04. import java.io.FileNotFoundException;
05. import java.io.IOException;
06. import java.text.SimpleDateFormat;
07. import java.util.Date;
08.  
09. import android.annotation.SuppressLint;
10. import android.content.ContentResolver;
11. import android.graphics.Bitmap;
12. import android.graphics.BitmapFactory;
13. import android.graphics.Matrix;
14. import android.net.Uri;
15.  
16. public class HelpUtil {
17. /**
18. * 根据图片路径获取本地图片的Bitmap
19. *
20. * @param url
21. * @return
22. */
23. public static Bitmap getBitmapByUrl(String url) {
24. FileInputStream fis = null;
25. Bitmap bitmap = null;
26. try {
27. fis = new FileInputStream(url);
28. bitmap = BitmapFactory.decodeStream(fis);
29.  
30. catch (FileNotFoundException e) {
31. // TODO Auto-generated catch block
32. e.printStackTrace();
33. bitmap = null;
34. finally {
35. if (fis != null) {
36. try {
37. fis.close();
38. catch (IOException e) {
39. // TODO Auto-generated catch block
40. e.printStackTrace();
41. }
42. fis = null;
43. }
44. }
45.  
46. return bitmap;
47. }
48.  
49. /**
50. * bitmap旋转90度
51. *
52. * @param bitmap
53. * @return
54. */
55. public static Bitmap createRotateBitmap(Bitmap bitmap) {
56. if (bitmap != null) {
57. Matrix m = new Matrix();
58. try {
59. m.setRotate(90, bitmap.getWidth() / 2, bitmap.getHeight() / 2);// 90就是我们需要选择的90度
60. Bitmap bmp2 = Bitmap.createBitmap(bitmap, 00,
61. bitmap.getWidth(), bitmap.getHeight(), m, true);
62. bitmap.recycle();
63. bitmap = bmp2;
64. catch (Exception ex) {
65. System.out.print("创建图片失败!" + ex);
66. }
67. }
68. return bitmap;
69. }
70.  
71. public static Bitmap getBitmapByUri(Uri uri,ContentResolver cr){
72. Bitmap bitmap = null;
73. try {
74. bitmap = BitmapFactory.decodeStream(cr
75. .openInputStream(uri));
76. catch (FileNotFoundException e) {
77. // TODO Auto-generated catch block
78. e.printStackTrace();
79. bitmap = null;
80. }
81. return bitmap;
82. }
83.  
84. /**
85. * 获取格式化日期字符串
86. * @param date
87. * @return
88. */
89. @SuppressLint("SimpleDateFormat")
90. public static String getDateFormatString(Date date) {
91. if (date == null)
92. date = new Date();
93. String formatStr = new String();
94. SimpleDateFormat matter = new SimpleDateFormat("yyyyMMdd_HHmmss");
95. formatStr = matter.format(date);
96. return formatStr;
97. }
98. }

2.主函数类MainActivity.java

 

 

view source print ?
01. package com.example.camerasurfacedemo;
02.  
03. import android.app.Activity;
04. import android.content.Intent;
05. import android.net.Uri;
06. import android.os.Bundle;
07. import android.text.TextUtils;
08. import android.view.View;
09. import android.view.View.OnClickListener;
10. import android.widget.Button;
11. import android.widget.ImageView;
12.  
13. public class MainActivity extends Activity {
14.  
15. private Button goCameraBtn;
16. private ImageView showCameraIv;
17. private static final int CAMERA_CODE = 1;
18. @Override
19. protected void onCreate(Bundle savedInstanceState) {
20. super.onCreate(savedInstanceState);
21. setContentView(R.layout.activity_main);
22.  
23. goCameraBtn = (Button)this.findViewById(R.id.id_go_camera_btn);
24. goCameraBtn.setOnClickListener(new OnClickListener(){
25.  
26. @Override
27. public void onClick(View v) {
28. processGoCamera();
29. }
30.  
31. });
32.  
33. showCameraIv = (ImageView)this.findViewById(R.id.id_show_camera_iv);
34. showCameraIv.setOnClickListener(new OnClickListener(){
35.  
36. @Override
37. public void onClick(View v) {
38. processShowCamera(v);
39. }
40.  
41. });
42. }
43.  
44. /**
45. * 处理进入camera事件
46. */
47. private void processGoCamera(){
48. Intent intent = new Intent();
49. intent.setClass(this, CameraActivity.class);
50. startActivityForResult(intent,CAMERA_CODE);
51. }
52.  
53. /**
54. * 处理图片跳转进入预览界面
55. */
56. private void processShowCamera(View v){
57. Intent intent = new Intent();
58. intent.setClass(this, PreviewActivity.class);
59. /**
60. * 将图片url传给PreviewActivity
61. */
62. intent.putExtra("cameraUrl", v.getContentDescription().toString());
63. startActivity(intent);
64. }
65.  
66. @Override
67. public void onActivityResult(int requestCode,int resultCode,Intent data){
68. super.onActivityResult(requestCode, resultCode, data);
69.  
70. if(RESULT_OK == resultCode){
71. if(CAMERA_CODE == requestCode){
72. /**
73. * 获取activity返回的url
74. */
75. Uri uri = data.getData();
76. String url = uri.toString().substring(uri.toString().indexOf("///")+2);
77. if(url != null && !TextUtils.isEmpty(url)){
78. showCameraIv.setContentDescription(url);
79. showCameraIv.setImageBitmap(HelpUtil.getBitmapByUrl(url));
80. }
81. }
82. }
83.  
84. }
85.  
86. }

 

注意:这里通过startActivityForResult(intent,CAMERA_CODE)跳转和 onActivityResult(int requestCode,int resultCode,Intent data)返回拍照后的图片路径信息

3.自定义Camera preview类CameraActivity.java

 

view source print ?
001. package com.example.camerasurfacedemo;
002.  
003. import java.io.File;
004. import java.io.FileNotFoundException;
005. import java.io.FileOutputStream;
006. import java.io.IOException;
007. import java.util.Date;
008.  
009. import android.annotation.SuppressLint;
010. import android.app.Activity;
011. import android.content.Context;
012. import android.content.Intent;
013. import android.content.pm.PackageManager;
014. import android.graphics.ImageFormat;
015. import android.hardware.Camera;
016. import android.hardware.Camera.CameraInfo;
017. import android.hardware.Camera.Parameters;
018. import android.hardware.Camera.PictureCallback;
019. import android.net.Uri;
020. import android.os.Bundle;
021. import android.os.Environment;
022. import android.util.Log;
023. import android.view.SurfaceHolder;
024. import android.view.SurfaceView;
025. import android.view.View;
026. import android.view.View.OnClickListener;
027. import android.view.Window;
028. import android.widget.Button;
029.  
030. public class CameraActivity extends Activity implements OnClickListener,
031. SurfaceHolder.Callback {
032.  
033. private static final String TAG = CameraActivity.class.getSimpleName();
034. private static final int MEDIA_TYPE_IMAGE = 1;
035. private Button switchCameraBtn, captureBtn;
036. private SurfaceView surfaceSv;
037.  
038. private SurfaceHolder mHolder;
039. private Camera mCamera;
040. // 0表示后置,1表示前置
041. private int cameraPosition = 1;
042.  
043. @Override
044. protected void onCreate(Bundle savedInstanceState) {
045. super.onCreate(savedInstanceState);
046. // 不显示标题
047. this.requestWindowFeature(Window.FEATURE_NO_TITLE);
048. setContentView(R.layout.activity_camera);
049.  
050. findById();
051. initData();
052. }
053.  
054. /**
055. * 初始化view
056. */
057. private void findById() {
058. switchCameraBtn = (Button) this.findViewById(R.id.id_switch_camera_btn);
059. captureBtn = (Button) this.findViewById(R.id.id_capture_btn);
060. surfaceSv = (SurfaceView) this.findViewById(R.id.id_area_sv);
061.  
062. switchCameraBtn.setOnClickListener(this);
063. captureBtn.setOnClickListener(this);
064. }
065.  
066. /**
067. * 初始化相关data
068. */
069. private void initData() {
070. // 获得句柄
071. mHolder = surfaceSv.getHolder();
072. // 添加回调
073. mHolder.addCallback(this);
074. }
075.  
076. @Override
077. public void onStart() {
078. super.onStart();
079. if (this.checkCameraHardware(this) && (mCamera == null)) {
080. // 打开camera
081. mCamera = getCamera();
082. if (mHolder != null) {
083. setStartPreview(mCamera,mHolder);
084. }
085. }
086. }
087.  
088. private Camera getCamera() {
089. Camera camera = null;
090. try {
091. camera = Camera.open();
092. catch (Exception e) {
093. // Camera is not available (in use or does not exist)
094. camera = null;
095. Log.e(TAG, "Camera is not available (in use or does not exist)");
096. }
097. return camera;
098. }
099.  
100. @Override
101. public void onPause() {
102. super.onPause();
103. /**
104. * 记得释放camera,方便其他应用调用
105. */
106. releaseCamera();
107. }
108.  
109. @Override
110. public void onDestroy() {
111. super.onDestroy();
112. }
113.  
114. /**
115. * 释放mCamera
116. */
117. private void releaseCamera() {
118. if (mCamera != null) {
119. mCamera.setPreviewCallback(null);
120. mCamera.stopPreview();// 停掉原来摄像头的预览
121. mCamera.release();
122. mCamera = null;
123. }
124. }
125.  
126. @Override
127. public void onClick(View v) {
128. switch (v.getId()) {
129. case R.id.id_switch_camera_btn:
130. // 切换前后摄像头
131. int cameraCount = 0;
132. CameraInfo cameraInfo = new CameraInfo();
133. cameraCount = Camera.getNumberOfCameras();// 得到摄像头的个数
134.  
135. for (int i = 0; i < cameraCount; i++) {
136. Camera.getCameraInfo(i, cameraInfo);// 得到每一个摄像头的信息
137. if (cameraPosition == 1) {
138. // 现在是后置,变更为前置
139. if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
140. /**
141. * 记得释放camera,方便其他应用调用
142. */
143. releaseCamera();
144. // 打开当前选中的摄像头
145. mCamera = Camera.open(i);
146. // 通过surfaceview显示取景画面
147. setStartPreview(mCamera,mHolder);
148. cameraPosition = 0;
149. break;
150. }
151. else {
152. // 现在是前置, 变更为后置
153. if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
154. /**
155. * 记得释放camera,方便其他应用调用
156. */
157. releaseCamera();
158. mCamera = Camera.open(i);
159. setStartPreview(mCamera,mHolder);
160. cameraPosition = 1;
161. break;
162. }
163. }
164.  
165. }
166. break;
167. case R.id.id_capture_btn:
168. // 拍照,设置相关参数
169. Camera.Parameters params = mCamera.getParameters();
170. params.setPictureFormat(ImageFormat.JPEG);
171. params.setPreviewSize(800400);
172. // 自动对焦
173. params.setFocusMode(Parameters.FOCUS_MODE_AUTO);
174. mCamera.setParameters(params);
175. mCamera.takePicture(nullnull, picture);
176. break;
177. }
178. }
179.  
180. @Override
181. public void surfaceCreated(SurfaceHolder holder) {
182.  
183. setStartPreview(mCamera,mHolder);
184. }
185.  
186. @Override
187. public void surfaceChanged(SurfaceHolder holder, int format, int width,
188. int height) {
189. // If your preview can change or rotate, take care of those events here.
190. // Make sure to stop the preview before resizing or reformatting it.
191.  
192. if (mHolder.getSurface() == null) {
193. // preview surface does not exist
194. return;
195. }
196.  
197. // stop preview before making changes
198. try {
199. mCamera.stopPreview();
200. catch (Exception e) {
201. // ignore: tried to stop a non-existent preview
202. }
203.  
204. // set preview size and make any resize, rotate or
205. // reformatting changes here
206.  
207. // start preview with new settings
208. setStartPreview(mCamera,mHolder);
209. }
210.  
211. @Override
212. public void surfaceDestroyed(SurfaceHolder holder) {
213. // 当surfaceview关闭时,关闭预览并释放资源
214. /**
215. * 记得释放camera,方便其他应用调用
216. */
217. releaseCamera();

你可能感兴趣的:(camera)