zoukankan      html  css  js  c++  java
  • Android+Camera+SurfaceView自定义相机系列(一)

    本文主要介绍如何使用camera+surfaceview来自定义相机,我们使用自定义相机进行拍照、扫描二维码等等。Camera是属于硬件部分,在开发中会经常遇到如何使用相机。在上一篇文章中介绍了如何动态的申请权限,使用相机是需要动态申请权限的。

    根据官方文档介绍在拍摄照片时,用户通常要先看到拍摄目标的预览效果,然后再按下快门。为此,您可以使用 SurfaceView 绘制摄像头传感器需要获取的内容的预览效果。SurfaceView是由SurfaceHolder来操控。

    一、首先创建一个SurfaceView,并实现SurfaceHolder的回调。由于Camera在SurfaceView中是通过SurfaceHolder 使得Surfaceview能够预览Camera返回的数据,因此我们需要实现SurfaceHolder 的回调,关于SurfaceView 、Surface 、 SurfaceHolder三者的关系可以参考这篇博客

    SurfaceHolder中有一个Callbcak接口,它有3个回调方法

    • surfaceCreated(SurfaceHolder holder)
      surface第一次创建时回调

    • surfaceChanged(SurfaceHolder holder, int format, int width,
      int height)
      surface变化的时候回调(格式/大小)

    • surfaceDestroyed(SurfaceHolder holder)
      surface销毁的时候回调

    SurfaceView继承自View,其中有两个成员变量,一个是Surface对象,一个是SuraceHolder对象。

    • SurfaceView把Surface显示在屏幕上
    • SurfaceView通过SuraceHolder告诉我们Surface的状态(创建、变化、销毁)
    • 通过getHolder()方法获得当前SurfaceView的SuraceHolder对象,然后就可以对SuraceHolder对象添加回调来监听Surface的状态

    SurfaceView小结

    1. SurfaceView是一个view对象,用于在屏幕上显示相机的预览画面
    2. SurfaceView中有两个对象,Surface和SuraceHolder。 我们通过SuraceHolder中的回调可以知道Surface的状态(创建、变化、销毁)
    3. 通过getHolder()方法获得当前SurfaceView的SuraceHolder对象

    代码如下:

     1 package com.example.camera;
     2 
     3 import androidx.annotation.NonNull;
     4 import androidx.appcompat.app.AppCompatActivity;
     5 import androidx.core.app.ActivityCompat;
     6 import androidx.core.content.ContextCompat;
     7 
     8 import android.Manifest;
     9 import android.content.pm.PackageManager;
    10 import android.hardware.Camera;
    11 import android.os.Bundle;
    12 import android.view.SurfaceHolder;
    13 import android.view.SurfaceView;
    14 import android.view.Window;
    15 import android.view.WindowManager;
    16 
    17 import java.io.IOException;
    18 
    19 public class MainActivity extends AppCompatActivity {
    20     private static final String TAG = "MainActivity";
    21 
    22     /*
    23     * 创建SurfaceHolder,Camera,SurfaceViiew;
    24     * */
    25     private SurfaceHolder surfaceHolder;
    26     private Camera camera;
    27     private SurfaceView surfaceView;
    28 
    29     private static final String[] permission = new String[] {
    30             Manifest.permission.CAMERA,
    31             Manifest.permission.WRITE_EXTERNAL_STORAGE
    32     };
    33 
    34     @Override
    35     protected void onCreate(Bundle savedInstanceState) {
    36         super.onCreate(savedInstanceState);
    37 
    38         //去除顶部状态栏
    39         requestWindowFeature(Window.FEATURE_NO_TITLE);
    40         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
    41         setContentView(R.layout.activity_main);
    42         // Android 6.0相机动态权限检查
    43         if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)== PackageManager.PERMISSION_GRANTED){
    44         }else {
    45             ActivityCompat.requestPermissions(this,permission,1);
    46         }
    47 
    48         surfaceView = findViewById(R.id.surfaceView);
    49         surfaceHolder = surfaceView.getHolder();
    50         surfaceHolder.addCallback(new SurfaceHolder.Callback() {
    51             @Override
    52             public void surfaceCreated(@NonNull SurfaceHolder holder) {
    53                 surfaceHolder = holder;
    54                  camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
    55                 try {
    56                     camera.setPreviewDisplay(surfaceHolder);
    57                 } catch (IOException e) {
    58                     e.printStackTrace();
    59                 }
    60                 camera.startPreview();
    61 
    62             }
    63 
    64             @Override
    65             public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
    66 
    67             }
    68 
    69             @Override
    70             public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
    71 
    72             }
    73         });
    74 
    75 
    76 
    77 
    78 
    79     }
    80 }

    activity_main.xml布局文件如下:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     xmlns:app="http://schemas.android.com/apk/res-auto"
     4     xmlns:tools="http://schemas.android.com/tools"
     5     android:layout_width="match_parent"
     6     android:layout_height="match_parent"
     7     tools:context=".MainActivity">
     8 
     9     <SurfaceView
    10         android:id="@+id/surfaceView"
    11         android:layout_width="match_parent"
    12         android:layout_height="match_parent" />
    13     <Button
    14         android:id="@+id/switch_camer"
    15         android:layout_width="wrap_content"
    16         android:layout_height="wrap_content"
    17         android:layout_gravity="bottom|center"
    18         android:text="切换相机"
    19         
    20         />
    21 
    22 </FrameLayout>

    在这里我们已经初步的完成了在surfaceView中显示camare的画面了,但是打开之后,会发现显示的画面是扭曲的,无论怎么翻转手机都是不可以的。这个问题后面解决。

    在这里总结一下如何使用Camera+SurfaceView来显示画面:

    1、首先获得布局文件中定义的SurfaceView;

    2、使用surfaceHolder来操控surfaceView,不能直接对surfaceView操控;
     
    3、创建surfaceHolder的callback回调接口;
     
    4、在接口的surfaceCreated中实现camera与surfaceView的绑定;
     
    5、使用open打开摄像头open(1)代表前置摄像头,0代表后置摄像头;
     
    6、然后显示预览画面。
    这些就是camera与surfaceView的使用。
     
    二、解决问题
    由于Camera的各种参数很多,上面涉及的预览画面出现的错误是因为设置的预览画面角度问题。加上一行setDisplayOrientation的代码就可以解决了
     1 @Override
     2             public void surfaceCreated(@NonNull SurfaceHolder holder) {
     3                 surfaceHolder = holder;
     4                  camera = Camera.open(1);
     5 
     6 
     7                  camera.setDisplayOrientation(90);
     8 
     9 
    10                 try {
    11                     camera.setPreviewDisplay(surfaceHolder);
    12                 } catch (IOException e) {
    13                     e.printStackTrace();
    14                 }
    15                 camera.startPreview();
    16 
    17             }
     
  • 相关阅读:
    visual basic VB.NET实例系列教程第三节(常用循环结构之乘法表与数列)
    visual basic VB.NET实例系列教程第二节(好玩又有趣的龟兔赛跑程序)
    visual basic VB.NET实例系列教程第一节(简单实用抽奖程序)
    对DevSecOps的一点认识
    轻便的一句话反弹shell语句
    ActiveMQ 反序列化漏洞(CVE-2015-5254)复现
    《信息安全风险管理》梗概
    微信服务商分账功能开发(PHP)
    哈夫曼编码—文件的压缩与解压(Java)
    哈夫曼编码—数据压缩与解压(Java)
  • 原文地址:https://www.cnblogs.com/hequnwang/p/14224132.html
Copyright © 2011-2022 走看看