19、照相机技术

照相机有哪些功能

     Android SDK支持操作Android设备内置的照相机。从Android2.3开始,支持操作多个摄像头(主要指前置摄像头和后置照相机)。通过照相机可以拍照和录像。

编写拍照程序需要考虑哪些方面
是否支持照相机
 
快速拍照和定制拍照
 
存储
照相机涉及到的主要API
Camera

SurfaceView、

MediaRecorder
Intent
拍照和摄像程序可能涉及到的权限和特性

<uses-permission android:name="android.permission.CAMERA" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.RECORD_AUDIO" />

<uses-feature android:name="android.hardware.camera" />

DEMO1
拍照Demo
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent"
 5     android:orientation="vertical" >
 6 
 7     <Button
 8         android:id="@+id/btnTakePicture"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:text="拍照" />
12 
13     <ImageView
14         android:id="@+id/imageview"
15         android:layout_width="320dp"
16         android:layout_height="240dp" />
17 
18 </LinearLayout>
 1 import android.app.Activity;
 2 import android.content.Intent;
 3 import android.graphics.Bitmap;
 4 import android.os.Bundle;
 5 import android.provider.MediaStore;
 6 import android.view.View;
 7 import android.view.View.OnClickListener;
 8 import android.widget.Button;
 9 import android.widget.ImageView;
10 
11 public class Main extends Activity implements OnClickListener {
12     private ImageView imageView;
13 
14     @Override
15     public void onCreate(Bundle savedInstanceState) {
16         super.onCreate(savedInstanceState);
17         setContentView(R.layout.main);
18 
19         Button btnTakePicture = (Button) findViewById(R.id.btnTakePicture);
20         btnTakePicture.setOnClickListener(this);
21 
22         imageView = (ImageView) findViewById(R.id.imageview);
23     }
24 
25     public void onClick(View view) {
26         // 调用系统拍照
27         Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
28         // 显示拍照窗口
29         startActivityForResult(intent, 1);
30     }
31     
32     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
33         if (requestCode == 1) {
34             if (resultCode == Activity.RESULT_OK) {
35                 Bitmap cameraBitmap = (Bitmap) data.getExtras().get("data");
36                 imageView.setImageBitmap(cameraBitmap);
37             }
38         }
39     }
40 
41 }
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="cn.eoe.system.camera" android:versionCode="1"
 4     android:versionName="1.0">
 5     <application android:icon="@drawable/icon" android:label="@string/app_name">
 6         <activity android:name=".Main" android:label="@string/app_name">
 7             <intent-filter>
 8                   <action android:name="android.intent.action.MAIN" />
 9                 <category android:name="android.intent.category.LAUNCHER" />
10             </intent-filter>
11         </activity>    
12     </application>
13     <uses-sdk android:minSdkVersion="7" />
14 </manifest> 
录像Demo
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent"
 5     android:orientation="vertical" >
 6 
 7     <Button
 8         android:id="@+id/btnTakePicture"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:text="录像" />
12 
13     <VideoView
14         android:id="@+id/videoview"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content" />
17 
18 </LinearLayout>
 1 import android.app.Activity;
 2 import android.content.Intent;
 3 import android.database.Cursor;
 4 import android.net.Uri;
 5 import android.os.Bundle;
 6 import android.provider.MediaStore;
 7 import android.view.View;
 8 import android.view.View.OnClickListener;
 9 import android.widget.Button;
10 import android.widget.MediaController;
11 import android.widget.VideoView;
12 
13 public class Main extends Activity implements OnClickListener {
14     public VideoView videoView;
15 
16     @Override
17     public void onCreate(Bundle savedInstanceState) {
18         super.onCreate(savedInstanceState);
19         setContentView(R.layout.main);
20         Button btnTakePicture = (Button) findViewById(R.id.btnTakePicture);
21         btnTakePicture.setOnClickListener(this);
22 
23         videoView = (VideoView) findViewById(R.id.videoview);
24 
25     }
26     
27     public void onClick(View view) {
28         Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
29         startActivityForResult(intent, 1);
30     }
31 
32     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
33         if (requestCode == 1) {
34             if (resultCode == Activity.RESULT_OK) {
35                 Uri uri = data.getData();
36                 Cursor cursor = this.getContentResolver().query(uri, null,
37                         null, null, null);
38 
39                 if (cursor.moveToFirst()) {
40                     // 取出路径
41                     String videoPath = cursor.getString(cursor
42                             .getColumnIndex("_data"));
43                     // 加载
44                     videoView.setVideoURI(Uri.parse(videoPath));
45                     // 设置视频控制控件(停止,快进等)。
46                     videoView.setMediaController(new MediaController(this));
47                     // 播放。
48                     videoView.start();
49                 }
50             }
51         }
52     }
53 
54 }
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="cn.eoe.record.video" android:versionCode="1"
 4     android:versionName="1.0">
 5     <application android:icon="@drawable/icon" android:label="@string/app_name">
 6         <activity android:name="Main" android:label="@string/app_name">
 7             <intent-filter>
 8                   <action android:name="android.intent.action.MAIN" />
 9                 <category android:name="android.intent.category.LAUNCHER" />
10             </intent-filter>
11         </activity>    
12     </application>
13     <uses-sdk android:minSdkVersion="7" />
14 </manifest> 
 
定制拍照程序的步骤
打开照相机:Camera.open
 
创建SurfaceView对象
 
添加回调事件监听器(SurfaceHolder.addCallback)
 
预览(Camera.startPreview)
 
拍照(Camera.takePicture)
检测Android设备是否支持照相机

private boolean checkCameraHardware(Context context) {

    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA))

    {  return true; }  else  {   return false; }

}

DEMO2
  1 package cn.eoe.custom.camera;
  2 
  3 import java.io.File;
  4 import java.io.FileOutputStream;
  5 import java.util.List;
  6 
  7 import android.app.Activity;
  8 import android.content.Context;
  9 import android.hardware.Camera;
 10 import android.hardware.Camera.PictureCallback;
 11 import android.hardware.Camera.Size;
 12 import android.os.Bundle;
 13 import android.view.SurfaceHolder;
 14 import android.view.SurfaceView;
 15 import android.view.View;
 16 import android.view.View.OnClickListener;
 17 import android.view.ViewGroup;
 18 import android.view.Window;
 19 import android.view.WindowManager;
 20 
 21 public class CustomCameraActivity extends Activity {
 22     private Camera mCamera;
 23     private Preview mPreview;
 24 
 25     @Override
 26     protected void onCreate(Bundle savedInstanceState) {
 27         super.onCreate(savedInstanceState);
 28         // 设置为全屏
 29         requestWindowFeature(Window.FEATURE_NO_TITLE);
 30         getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
 31         mPreview = new Preview(this);
 32         setContentView(mPreview);
 33     }
 34 
 35     protected void onResume() {
 36         super.onResume();
 37         // 打开照相机
 38         mCamera = Camera.open();
 39         mPreview.setCamera(mCamera);
 40     }
 41 
 42     protected void onPause() {
 43         super.onPause();
 44 
 45         if (mCamera != null) {
 46             mCamera.release();
 47             mCamera = null;
 48             mPreview.setCamera(null);
 49         }
 50     }
 51 
 52     class Preview extends ViewGroup implements SurfaceHolder.Callback,
 53             OnClickListener {
 54 
 55         SurfaceView mSurfaceView;
 56         SurfaceHolder mHolder; // 存储事件回掉
 57         Size mPreviewSize;  // 当前窗口预览尺寸
 58         List<Size> mSupportedPreviewSizes; // 相机中的预览尺寸
 59         Camera mCamera;
 60         Context mContext;  
 61 
 62         public Preview(Context context) {
 63             super(context);
 64             mContext = context;
 65             mSurfaceView = new SurfaceView(context);
 66             addView(mSurfaceView);
 67             mHolder = mSurfaceView.getHolder();
 68             mHolder.addCallback(this);
 69 
 70         }
 71 
 72         public void setCamera(Camera camera) {
 73             mCamera = camera;
 74             if (mCamera != null) {
 75                 // 获得当前相机可支持预览的尺寸。
 76                 mSupportedPreviewSizes = mCamera.getParameters()
 77                         .getSupportedPictureSizes();
 78                 // 调整布局。
 79                 requestLayout();
 80             }
 81         }
 82 
 83         private PictureCallback mPictureCallback = new PictureCallback() {
 84 
 85             @Override
 86             public void onPictureTaken(byte[] data, Camera camera) {
 87                 mCamera.startPreview();
 88                 File pictureFile = new File("/sdcard/image.jpg");
 89                 try {
 90                     FileOutputStream fos = new FileOutputStream(pictureFile);
 91                     fos.write(data);
 92                     fos.close();
 93                 } catch (Exception e) {
 94                     // TODO: handle exception
 95                 }
 96 
 97             }
 98         };
 99 
100         public void onClick(View view) {
101             mCamera.takePicture(null, null, mPictureCallback);
102         }
103 
104         @Override
105         public void surfaceChanged(SurfaceHolder holder, int format, int width,
106                 int height) {
107             // 设置预览的尺寸(不支持比如:200 200这种尺寸)。
108             Camera.Parameters parameters = mCamera.getParameters();
109             parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
110 
111             mCamera.setParameters(parameters);
112             mCamera.startPreview();  // 预览
113 
114         }
115 
116         @Override
117         public void surfaceCreated(SurfaceHolder holder) {
118             try {
119                 if (mCamera != null) {
120                     // 将 Camera和SurfaceView进行一个关联。
121                     mCamera.setPreviewDisplay(holder);
122                 }
123             } catch (Exception e) {
124                 // TODO: handle exception
125             }
126 
127         }
128 
129         @Override
130         public void surfaceDestroyed(SurfaceHolder holder) {
131             // TODO Auto-generated method stub
132             if (mCamera != null) {
133                 // 停止预览
134                 mCamera.stopPreview();
135             }
136         }
137 
138         @Override  // 调整预览尺寸。
139         protected void onLayout(boolean changed, int l, int t, int r, int b) {
140             if (changed && getChildCount() > 0) {  //子视图
141                 // 获得子视图。
142                 final View child = getChildAt(0);
143 
144                 // viewGroup
145                 int width = r - l;    
146                 int height = b - t;    
147 
148                 // 实际窗口尺寸。
149                 int previewWidth = width;
150                 int previewHeight = height;
151 
152                 // mPreviewSize 图像产生的。
153                 if (mPreviewSize != null) { 
154                     // 把前两个初始值覆盖。 
155                     previewWidth = mPreviewSize.width;
156                     previewHeight = mPreviewSize.height;
157                 }
158                 // 手机屏幕的宽高比大于采集图像的宽高比。
159                 if (width * previewHeight > height * previewWidth) {
160                     final int scaledChildWidth = previewWidth * height
161                             / previewHeight;
162                     // child.layout((width - scaledChildWidth)/2,
163                     // 0,(width+scaledChildWidth)/2,height);
164 
165                     child.layout(100, 100, 340, 240);
166                 } else {
167                     final int scaledChildHeight = previewHeight * width
168                             / previewWidth;
169                     child.layout(0, (height - scaledChildHeight) / 2, width,
170                             (height + scaledChildHeight) / 2);
171                 }
172 
173             }
174 
175         }
176 
177         private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
178             double ASPECT_TOLERANCE = 0.1;
179             double targetRatio = (double) w / h;
180             if (sizes == null)
181                 return null;
182 
183             Size optimalSize = null;
184             double minDiff = Double.MAX_VALUE;
185             int targetHeight = h;
186 
187             for (Size size : sizes) {
188                 double ratio = (double) size.width / size.height;
189                 if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
190                     continue;
191                 }
192                 if (Math.abs(size.height - targetHeight) < minDiff) {
193                     optimalSize = size;
194                     minDiff = Math.abs(size.height - targetHeight);
195                 }
196             }
197 
198             if (optimalSize == null) {
199                 minDiff = Double.MAX_VALUE;
200                 for (Size size : sizes) {
201                     if (Math.abs(size.height - targetHeight) < minDiff) {
202                         optimalSize = size;
203                         minDiff = Math.abs(size.height - targetHeight);
204                     }
205                 }
206             }
207             return optimalSize;
208         }
209 
210         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
211             int width = resolveSize(getSuggestedMinimumWidth(),
212                     widthMeasureSpec);
213             int height = resolveSize(getSuggestedMinimumHeight(),
214                     heightMeasureSpec);
215 
216             setMeasuredDimension(width, height);
217 
218             if (mSupportedPreviewSizes != null) {
219                 mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes,
220                         width, height);
221             }
222         }
223 
224     }
225 
226 }
 
原文地址:https://www.cnblogs.com/androidsj/p/3869892.html