zoukankan      html  css  js  c++  java
  • 控制摄像头拍照

    现在的智能手机和平板电脑一般都会提供摄像头拍照功能。在Android中提供了专门用于处理摄像头相关事件的类,即android.hardware包中的Camera类。Camera类没有构造方法,可以通过其提供的open()方法打开摄像头。打开摄像头后,可以通过Camera.Parameters类处理摄像头的拍照参数。拍照参数设置完成后,可以调用startPreview()方法预览拍照画面,也可以调用takePicture()方法进行拍照。结束程序时,可以调用Camera类的stopPreview()方法结束预览,并调用release()方法释放摄像头资源。Camera类常用的方法如表10.9所示。

    表10.9  Camera类常用的方法

    下面通过一个实例来说明控制摄像头拍照的具体过程。

    实例  实现控制摄像头拍照功能

    在Android Studio中创建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 SurfaceHolder sh = 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(View v) {
    
    04          // 如果摄像头为非预览模式,则打开相机
    
    05          if (!isPreview) {
    
    06              camera = Camera.open();                /打开相机
    
    07              isPreview = true;                       //设置为预览状态
    
    08          }
    
    09          try {
    
    10              camera.setPreviewDisplay(sh);           //设置用于显示预览的SurfaceView
    
    11              Camera.Parameters parameters = 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.PictureCallback jpeg = new Camera.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              FileOutputStream fos = new FileOutputStream(file); //创建一个文件输出流对象
    
    21              //将图片内容压缩为JPEG格式输出到输出流对象中
    
    22              bm.compress(Bitmap.CompressFormat.JPEG, 100, fos);
    
    23              //将缓冲区中的数据全部写出到输出流中
    
    24              fos.flush();
    
    25              fos.close();                            //关闭文件输出流对象
    
    26          } catch (FileNotFoundException e) {
    
    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(View v) {
    
    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卡读写权限。

     

    本文来自明日科技出版的《零基础学Android,转载请注明出处!!!

  • 相关阅读:
    DeepEarth更新到Silverlight 4了
    Silverlight & Blend动画设计系列八:拖放(DragDrop)操作与拖放行为(DragBehavior)
    VS2010之vb.net:细节决定成败
    iVIEW: An Intelligent Video over InternEt and Wireless Access System
    Tianya Doc
    治疗咳嗽
    一个 研究 可视化的个人博客
    Windows自启动方式完全总结
    JAVA连接DB2
    JSP 与 Discuz整合
  • 原文地址:https://www.cnblogs.com/mrxy/p/8242232.html
Copyright © 2011-2022 走看看