控制摄像头拍照
现在的智能手机和平板电脑一般都会提供摄像头拍照功能。在Android中提供了专门用于处理摄像头相关事件的类,即android.hardware包中的Camera类。Camera类没有构造方法,可以通过其提供的open()方法打开摄像头。打开摄像头后,可以通过Camera.Parameters类处理摄像头的拍照参数。拍照参数设置完成后,可以调用startPreview()方法预览拍照画面,也可以调用takePicture()方法进行拍照。结束程序时,可以调用Camera类的stopPreview()方法结束预览,并调用release()方法释放摄像头资源。Camera类常用的方法如表10.9所示。
表10.9 Camera类常用的方法
方 法 | 描 述 |
getParameters() | 用于获取摄像头参数 |
Camera.open() | 用于打开摄像头 |
release() | 用于释放摄像头资源 |
setParameters(Camera.Parameters params) | 用于设置摄像头的拍照参数 |
setPreviewDisplay(SurfaceHolder holder) | 用于为摄像头指定一个用来显示预览画面的SurfaceView |
startPreview() | 用于开始预览画面 |
takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg) | 用于进行拍照 |
stopPreview() | 用于停止预览 |
下面通过一个实例来说明控制摄像头拍照的具体过程。
实例 实现控制摄像头拍照功能
在AndroidStudio中创建Module,名称为“Camera”,在该Module中实现本实例,具体步骤如下。
(1)修改布局文件activity_main.xml,首先将默认添加的布局管理器修改为帧布局管理器,然后将TextView组件删除,再添加一个SurfaceView组件(用于显示摄像头预览画面),最后添加一个预览按钮和一个拍照按钮。具体代码请参见光盘。
(2)打开MainActivity类,该类继承Activity,然后在该类中,定义所需的成员变量,关键代码如下:
01 private Camera camera; //定义相机对象 02 private boolean isPreview = false; //定义非预览状态
(3)在MainActivity类的onCreate()方法中,首先设置全屏显示,然后判断手机是否安装SD卡,关键代码如下:
01 //设置全屏显示 02 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 03 WindowManager.LayoutParams.FLAG_FULLSCREEN); 04 if (!Environment.getExternalStorageState().equals( //判断手机是否安装SD卡 05 Environment.MEDIA_MOUNTED)){ 06 Toast.makeText(this,"请安装SD卡!", Toast.LENGTH_SHORT).show();// 提示安装SD卡 07 }
(4)获取SurfaceView组件与SurfaceHolder对象,用于显示摄像头预览,关键代码如下:
01 //获取SurfaceView组件,用于显示摄像头预览 02 SurfaceView sv = (SurfaceView) findViewById(R.id.surfaceView); 03 final SurfaceHoldersh = sv.getHolder(); //获取SurfaceHolder对象 04 //设置该SurfaceHolder自己不维护缓冲 05 sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 06 ImageButton preview = (ImageButton) findViewById(R.id.preview); //获取“预览”按钮 07 ImageButton takePicture = (ImageButton) findViewById(R.id.takephoto); //获取“拍照”按钮
(5)为预览按钮添加单击事件监听器,实现摄像头的预览功能,关键代码如下:
01 preview.setOnClickListener(new View.OnClickListener(){ //实现摄像头预览功能 02 @Override 03 public void onClick(Viewv) { 04 // 如果摄像头为非预览模式,则打开相机 05 if (!isPreview) { 06 camera = Camera.open(); /打开相机 07 isPreview = true; //设置为预览状态 08 } 09 try { 10 camera.setPreviewDisplay(sh); //设置用于显示预览的SurfaceView 11 Camera.Parametersparameters = camera.getParameters(); //获取相机参数 12 parameters.setPictureFormat(PixelFormat.JPEG); //指定图片为JPEG图片 13 parameters.set("jpeg-quality", 80); //设置图片的质量 14 camera.setParameters(parameters); //重新设置相机参数 15 camera.startPreview(); //开始预览 16 camera.autoFocus(null); //设置自动对焦 17 } catch (IOException e){ //输出异常信息 18 e.printStackTrace(); 19 } 20 } 21 });
(6)在MainActivity中,创建实现重新预览的方法resetCamera(),在该方法中,当isPreview变量的值为真时,调用摄像头的startPreview()方法开启预览,具体代码如下:
01 private void resetCamera(){ //创建resetCamera()方法,实现重新预览功能 02 if (!isPreview) { //如果为非预览模式 03 camera.startPreview(); //开启预览 04 isPreview = true; 05 } 06 }
(8)实现拍照的回调接口,在重写的onPictureTaken()方法中,首先根据拍照所得的数据创建位图,然后保存所拍摄的图片,再把保存的图片文件插入到系统图库,最后通知图库更新,具体代码如下:
01 02 //实现将照片保存到系统图库中 03 final Camera.PictureCallbackjpeg = newCamera.PictureCallback() { //照片回调函数 04 @Override 05 public void onPictureTaken(byte[] data, Camera camera) { 06 // 根据拍照所得的数据创建位图 07 final Bitmap bm =BitmapFactory.decodeByteArray(data,0, 08 data.length); 09 camera.stopPreview(); //停止预览 10 isPreview = false; //设置为非预览状态 11 //获取sd卡根目录 12 File appDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/Camera/"); 13 if (!appDir.exists()) { //如果该目录不存在 14 appDir.mkdir(); //创建该目录 15 } 16 //将获取的当前系统时间设置为照片名称 17 String fileName = System.currentTimeMillis()+ ".jpg"; 18 File file = new File(appDir, fileName); //创建文件对象 19 try { //保存拍到的图片 20 FileOutputStreamfos = new FileOutputStream(file); //创建一个文件输出流对象 21 //将图片内容压缩为JPEG格式输出到输出流对象中 22 bm.compress(Bitmap.CompressFormat.JPEG, 100, fos); 23 //将缓冲区中的数据全部写出到输出流中 24 fos.flush(); 25 fos.close(); //关闭文件输出流对象 26 } catch (FileNotFoundExceptione) { 27 e.printStackTrace(); 28 } catch (IOException e) { 29 e.printStackTrace(); 30 } 31 //将照片插入到系统图库 32 try { 33 MediaStore.Images.Media.insertImage(MainActivity.this.getContentResolver(), 34 file.getAbsolutePath(),fileName, null); 35 } catch (FileNotFoundException e) { 36 e.printStackTrace(); 37 } 38 //最后通知图库更新 39 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 40 Uri uri = Uri.fromFile(file); 41 intent.setData(uri); 42 MainActivity.this.sendBroadcast(intent); //这个广播的目的就是更新图库 43 Toast.makeText(MainActivity.this, "照片保存至:" + file, Toast.LENGTH_LONG).show(); 44 resetCamera(); //调用重新预览resetCamera()方法 45 } 46 };
(9)在onCreate()方法中,为拍照按钮添加单击事件监听器,实现摄像头的拍照功能,关键代码如下:
01 takePicture.setOnClickListener(new View.OnClickListener(){ 02 @Override 03 public void onClick(Viewv) { 04 if (camera !=null) { //相机不为空 05 camera.takePicture(null, null,jpeg); //进行拍照 06 } 07 } 08 });
(10)重写Activity的onPause()方法,用于当暂停Activity时,停止预览并释放摄像头资源,具体代码如下:
01 @Override 02 protected void onPause(){ 03 if (camera != null){ //如果摄像头不为空 04 camera.stopPreview(); //停止预览 05 camera.release(); //释放资源 06 } 07 super.onPause(); 08 }
(11)由于本程序需要访问SD卡和控制摄像头,所以需要在AndroidManifest.xml文件中赋予程序访问SD卡和控制摄像头的权限,关键代码如下:
01 <!-- 授予程序可以向SD卡中保存文件的权限 --> 02 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 03 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 04 <!-- 授予程序使用摄像头的权限 --> 05 <uses-permission android:name="android.permission.CAMERA"/> 06 <uses-feature android:name="android.hardware.camera.autofocus"/> 07 <uses-feature android:name="android.hardware.camera"/> (12)在AndroidManifest.xml文件的<activity>标记中添加screenOrientation属性,设置其横屏显示,关键代码如下: android:screenOrientation="landscape"
(13)在工具栏中找到下拉列表框,选择要运行的应用(这里为Camera),再单击右侧的按钮,在显示的界面中,单击预览按钮,启动摄像头,单击拍照按钮进行拍照,如图10.9所示。
图10.9 预览与拍照
说明:本实例需要摄像头硬件的支持,这里我们使用真机测试。读者需要在手机中手动开启摄像头权限与sd卡读写权限。
感谢读者朋友对明日科技的支持,如果您对图书中的讲解及光盘源码有任何问题,可以直接登录http://www.mingrisoft.com上的社区进行发贴,把您的问题详细的说明一下,我们的技术人员会在那里给您回复!
本文来自明日科技出版的《零基础学Android》,转载请注明出处!!!
还没有评论,来说两句吧...