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 }

 

 

 

 

 

 

你可能感兴趣的:(技术)