Android利用SurfaceView显示Camera图像爬坑记(一)

Android Camera系列(一):SurfaceView+Camera 本文介绍了Camera+SurfaceView的基本操作及关键代码,但是你如果看github中代码会发现和文中出入很大。其原因在于文章我想用一种简单的方式让没有做过自定义Camera的人也能明白。而github中的项目我已经进行了多次重构、抽象。其中包括对Camera的抽象,定义ICameraManager接口。对预览的View的重构,定义BaseCameraView接口,以及预览视图的众多超类。 阅读详情

Android利用SurfaceView显示Camera图像爬坑记(一)

在这里插入图片描述

前言

前面文章《学习《实时Opencv处理后的Camera图像Android NDK方法》笔记》我们利用NDK处理OpenCV的图像,并在里面下载了一个DEMO进行处理,感觉不错,本着不能拿来就用的原则,并且对自己也是一个掌握和提高,所以准备在其基础上自己研究下怎么实现的。

前面文章里面用的是GLSurfaceView来处理里,为了从基础一点一点掌握,所以我先学习一下SurfaceView和Camera搭配实现。

代码演示

我们新建一个项目名称为surfaceviewdemo,首先修改一下布局文件activity_main.xml,在里面添加一个RelativeLayout,定义我们的surfaceviewlayout,到时候加载的时候把我们的SurfaceView直接add进来。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/surfaceviewlayout"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

然后我们新建一个类VaccaeSurfaceView,让其继承SurfaceView并且引入SurfaceHolder.Callback

在图中的红线处我们按ALT+ENTER,把其要加载重写的方法加入进来

定义我们的Camera相关参数,包括摄像头的ID,Camera变量及Camera的回调方法,最后再定义一个内部的SurfaceHolder

然后我们先修改构造函数,在构造函数中获取的SurfaceHolder,并在其中加入回调和基本的参数设置,如下图

而刚才生成的三个方法中,我们要在SurfaceCreated中加入开户摄像机的方法,在SurfaceDestroyed加入关闭摄像机的方法

开启摄像机

关闭摄像机

完整的VaccaeSurfaceView代码

package dem.vac.surfaceviewdemo;

import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * 作者:Vaccae
 * 邮箱:3657447@qq.com
 * 创建时间:2019-06-12 15:42
 * 功能模块说明:
 */
public class VaccaeSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    //Camera相关
    //设置摄像头ID,我们默认为后置
    private int mCameraIndex=Camera.CameraInfo.CAMERA_FACING_BACK;
    //定义摄像机
    private Camera camera;
    //定义Camera的回调方法
    private Camera.PreviewCallback previewCallback=new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] bytes, Camera camera) {
            synchronized (this) {
                Log.i("frame", "good");
            }
        }
    };

    //定义SurfaceHolder
    private SurfaceHolder holder;

    //构造函数
    public VaccaeSurfaceView(Context context) {
        super(context);
        //获取Holder
        holder=getHolder();
        //加入SurfaceHolder.Callback在类中implements
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        //保持屏幕常亮
        holder.setKeepScreenOn(true);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        //开启摄像机
        startCamera(mCameraIndex);
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        //关闭摄像机
        stopCamera();
    }

    //region 开启关闭Camera
    //开启摄像机
    private void startCamera(int mCameraIndex) {
        // 初始化并打开摄像头
        if (camera == null) {
            try {
                camera=Camera.open(mCameraIndex);
            } catch (Exception e) {
                return;
            }
            //获取Camera参数
            Camera.Parameters params=camera.getParameters();
            if (params.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                // 自动对焦
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            }
            params.setPreviewFormat(ImageFormat.NV21); // 设置预览图片格式
            params.setPictureFormat(ImageFormat.JPEG); // 设置拍照图片格式
            camera.setParameters(params);

            try {
                camera.setPreviewCallback(previewCallback);
                camera.setPreviewDisplay(holder);
                //旋转90度
                camera.setDisplayOrientation(90);
                camera.startPreview();
            } catch (Exception ex) {
                ex.printStackTrace();
                camera.release();
                camera=null;
            }
        }
    }

    //关闭摄像机
    private void stopCamera() {
        if (camera != null) {
            camera.setPreviewCallback(null);
            camera.stopPreview();
            camera.release();
            camera=null;
        }

    }
    //endregion

}


最后我们在MainActivity.java中加入怎么调用这个VaccaeSurfaceView的类

当然在Android6.0中呢还要加入Camera的权限申请

    void requestPermission(){
        final int REQUEST_CODE = 1;
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                            Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    REQUEST_CODE);
        }
    }

同时AndroidManifest.xml中也要加入

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" android:required="true"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="true"/>


最后

更多Android 学习资料可以扫码免费领取!

《Android编程入门指南》+Android基础课程资料包

内容概要:Android编程入门指南、Android基础课程资料包;

内容特点:条理清晰,含图像化表示更加易懂;

完整文档领取方式👇

《Android编程入门指南》

目录

img

第一章 Java语言基础从入门到熟悉

​ ● Java综述

​ ● Java基础

​ ● class

​ ● 面向对象

​ ● 容器

​ ● 多线程

​ ● IO

​ ● 正则表达式

​ ● 日历

​ ● 注解使用与简单说明

​ ● Java使用加密算法

img

第二章 Kotlin语言基础从入门到熟悉

​ ● Kotlin系列简介

​ ● 新建项目

​ ● 概念介绍

​ ● 常用写法

​ ● lambda

​ ● 高阶函数

​ ● 扩展函数

​ ● 协程

img

第三章 Android 技术栈从入门到熟悉

​ ● 开始

​ ● Activity

​ ● Service 服务

​ ● Broadcast 广播机制

​ ● Fragment

​ ● res应用资源

​ ● 权限

​ ● TextView 显示文字

​ ● EditText 用户输入

​ ● Button 按钮

​ ● ImageView 图片显示

​ ● Layout布局

​ ● DrawerLayout侧滑栏

​ ● RecyclerView 显示列表

​ ● 多线程

​ ● IO 操作

​ ● 存储

​ ● NetWork 网络

​ ● ProgressBar进度条

​ ● View

​ ● 自定义View

​ ● 动画

​ ● WebView

​ ● StatusBar

​ ● Camera相机

​ ● Media

​ ● Bluetooth 蓝牙

​ ● WiFi连接

​ ● 获取手机当前角度

​ ● launcher

​ ● AIDL

​ ● zip

​ ● Binder

​ ● Notification 通知

​ ● PackageManager

​ ● RTFSC

​ ● 设计模式

​ ● 第三方库

​ ● Android Studio

​ ● 模块化

​ ● Gradle

​ ● NDK

​ ● 调试

img

第四章 Android Jetpack 全家桶全面学习

Android 摄像头预览 ---- SurfaceView 和 Camera 由于,SurfaceView 的 UI 就可以在一个独立的线程中进行绘制,不会占用主线程资源(SurfaceView 一方面可以实现复杂而高效的 UI,另一方面又不会导致用户输入得不到及时响应)。由于surface可能被销毁,它只在 SurfaceHolder.Callback.surfaceCreated() 和 SurfaceHolder.Callback.surfaceDestroyed()之间有效,所以要确保渲染线程访问的是合法有效的Surface。渲染线程所要访问的各种变量应该作同步处理。 阅读详情

相关推荐

Android Camera+SurfaceView实现自定义拍照

对Activity强制横屏,保证预览方向正确。使用OrientationEventListener监听设备方向,判断竖拍时,旋转照片后再保存,保证竖拍时预览图片和保存后的图片方向一致。       运行效果:                       代码: TestCameraActivity.java package com.example.testcamera;

u012964281的专栏 8097

【HDR学习】利用SurfaceView显示图片

但它也有缺点,因为这个Surface不在View hierachy中,它的显示也不受View的属性控制,所以。SurfaceView属于View的子类它是专门为制作游戏而产生的,它的功能非常强大,最重要的是它支持OpenGL ES库,2D和3D的效果都可以实现。创建SurfaceView的时候需要实现SurfaceHolder.Callback接口,它可以用来监听SurfaceView的状态,比如:SurfaceView的改变 、SurfaceView的创建 、SurfaceView 销毁等。

cocoduco的博客 952

基于SurfaceView与Camera2 API的Android拍照功能实现

Android相机系统自诞生以来经历了多个版本的演进,其中最显著的技术跃迁之一便是从旧版CameraAPI(即 Camera1)过渡到功能更强大、控制粒度更精细的Camera2API。这一变革不仅提升了开发者对硬件底层能力的访问权限,也极大地增强了图像采集过程中的灵活性与可编程性。Camera2 API 于 Android 5.0(API Level 21)正式引入,采用基于“管道模型”的设计理念,将图像采集流程分解为多个可配置阶段,允许应用以近乎实时的方式干预曝光、对焦、帧率等关键参数。

weixin_29867767的博客 1106

SurfaceView介绍

What’s SurfaceView? 文档中说,SurfaceView就是在窗体上挖一个洞,它就显示在这个洞里。 类似这样: (就像是从望远镜里看出去一样) 而其他View就显示在窗体上,充当窗体本身。在继承关系上,SurfaceView是View的子类。 Why SurfaceView? 我们知道,出于安全考虑,子线程是无法直接touch到界面的,之前我们可以采用Handler机制实现子线程的“间接”touch,但性能不佳。而SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘

weixin_45651194的博客 728

Android SurfaceView 实现实时显示摄像头视频

Android SurfaceView 实现实时显示摄像头视频,详见博客:https://blog.youkuaiyun.com/qq_30297763/article/details/90241102

Android多种方式实现相机圆形预览的示例代码

效果图如下: 一、为预览控件设置圆角 为控件设置ViewOutlineProvider public RoundTextureView(Context context, AttributeSet attrs) { super(context, attrs); setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { Rect rect = new Rect(0, 0, view.getMeas

Android利用SurfaceView显示Camera图像爬坑记(四)

前言通过前面几篇,利用SurfaceView显示Camera的图像已经没什么问题了,接下来我们就要打磨一下细节,主要就是手机旋转的问题,考虑到我们会用横屏和竖屏的不同的情况。横竖屏问题用...

Vaccae的博客 709

医疗大模型实战——从零构建MedicalGPT全流程解析

本文详细解析了从零构建医疗大模型MedicalGPT的全流程实战。基于Qwen-7B模型与约195万条中文医疗数据,完整复现了增量预训练、监督微调与偏好对齐三大核心环节,并分享了如何在有限硬件资源下实现高效训练与部署,为开发者提供了可复现的医疗AI项目实战指南。

weixin_29193259的博客 553

Android利用SurfaceView显示Camera图像爬坑记(二)

前一章《[Android利用SurfaceView显示Camera图像爬坑记(一)我们已经实现了利用SurfaceView将Camera中的实时帧图像显示出来了,我们做这个的主要目录是想把每一帧的数据取出后通过OpenCV图像处理后,再实时显示出处理后的图像。要实现这个情况,我们首先要把Camera的实时数据存成Bitbmp的图像然后通过自己的处理显示出来,接下来我们就看看怎么样把Camera的实时图像都通过Bitbmp的方式显示出来。

Misdirection_XG的博客 606

Delphi开发者必备:CEF4Delphi跨平台浏览器嵌入实战指南(含Lazarus适配)

本文详细介绍了Delphi开发者如何利用CEF4Delphi实现跨平台浏览器嵌入,包括环境配置、Lazarus适配、ARM架构优化及Firemonkey集成等实战技巧。通过Chromium引擎的强大功能,开发者可以轻松为传统桌面应用添加现代浏览器特性,提升多平台开发效率。

weixin_29233333的博客 226

从零搭建IoT数据中台:STM32+WebSocket实现边缘设备与Web端实时双向通信

本文详细介绍了如何从零搭建基于STM32和WebSocket协议的IoT数据中台,实现边缘设备与Web端的实时双向通信。通过硬件选型、协议设计、服务器搭建及安全优化,提供了一套低延迟、高并发的企业级解决方案,适用于智能农业和工业监控等场景。

tea88的博客 749

Android利用SurfaceView显示Camera图像爬坑记(三)

前言前一章《Android利用SurfaceView显示Camera图像爬坑记(二)》我们已经利用SurfaceTexture通过生成的Bitmap图片用canvas画出显示,最后最后留...

Vaccae的博客 404

手把手教你解决uniapp中esbuild版本冲突问题(Mac版专属指南)

本文是针对Mac平台uniapp开发者的专属指南,详细解析了运行项目时常见的`Cannot start service`错误,即esbuild的Host版本与binary版本不匹配问题。文章从错误根源入手,提供了从快速应急处理到彻底根治的完整解决方案,包括手动替换二进制文件、锁定依赖版本、清理缓存及优化工具链配置,旨在帮助开发者高效解决版本冲突,恢复并稳定开发环境。

i0j1k2l3m的博客 458

Android利用SurfaceView显示Camera图像爬坑记(六) -- 用OpenCV进行Canny边缘检测

前言上一篇《Android利用SurfaceView显示Camera图像爬坑记(五) -- 在现有项目中加入NDK配置》中我们已经把NDK加入到SurfaceView实时图像显示了,这一...

Vaccae的博客 412

电力电子课设救星:用Simulink实现Buck变换器双闭环控制(PID调参技巧)

本文是电力电子课程设计的实用指南,详细讲解如何利用Simulink仿真平台实现Buck变换器的电压电流双闭环控制。文章核心聚焦于PID参数整定的实战技巧,提供了从手动调试口诀到MATLAB脚本自动优化的完整方案,旨在帮助学生高效完成课设,深入理解闭环控制原理并生成专业报告。

weixin_29179311的博客 296

中科蓝讯蓝牙开发:从源码到固件的自动化构建链路解析

本文详细解析了中科蓝讯AB530X蓝牙芯片从源码到最终固件的完整自动化构建链路。通过剖析prebuild.bat、GCC编译、postbuild.bat等关键环节,阐述了资源打包、配置生成、代码编译与固件合成的全过程,并重点介绍了如何实现一键编译与自动下载,为开发者高效进行嵌入式蓝牙开发提供清晰指南。

weixin_29193259的博客 121

4-2.Android Camera 之预览图像编码模板(SurfaceView)

在 Android 开发的早期阶段,Android 提供 `android.hardware.Camera` API,开发者用它来访问和控制设备的摄像头硬件

weixin_52173250的博客 1558

使用RustDesk或者AnyDesk的TCP隧道实现Codesys系列PLC的远程调试和下载

Codesys远程调试

exat500g的博客 7272

android camera系列(Camera1、Camera2、CameraX)的使用以及输出的图像格式

android中camera的预览和数据操作

知识共享,你我皆是知识的搬运工 6050

Ubuntu22.04安装ros(一键搞定)

然后发现可以一键安装,话不多说,直接终端输入如下指令。回车之后系统会自动安装ros。

m0_47313541的博客 7413

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Android Camera SurfaceView 获取预览数据

简介 Android 调用相机拍照,相信大家已经很熟悉了,通过Intent指定Action和Category,再通过startActivityForResult()获取到拍照的回调,这样获取的是系统相机,我们只能得到它拍摄的图片,再进行后续处理。有些功能,比如视频直播,美颜相机,需要对相机预览的图像进行处理,这时候我们就需要通过Android的相机Camera来进行操作。文章主要...

renlei0012的博客 6171

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Android Camera SurfaceView 预览拍照

本文已获得作者授权,本文作者:cain_huang原文链接:https://www.jianshu.com/p/9e0f3fc5a3b4Android使用 Camera ...

音视频开发进阶 1716

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android Camera开发避坑指南:SurfaceView预览的正确打开方式

本文深入探讨了Android Camera开发中SurfaceView预览的核心机制与常见问题。针对生命周期管理、预览尺寸适配、画面方向校正等关键难点,提供了经过实战检验的健壮实现方案与性能优化建议,帮助开发者避免黑屏、拉伸等典型问题,实现稳定高效的相机预览功能。

2w3e4r5t6y的博客 893

Android Camera SurfaceView

这个类图以camera预览为场景。从类图中可以看出, SurfaceView继承自(is-a)View SurfaceView中有一个SurfaceHolder,可以通过getHolder得到这个holder,这个holder有一个方法addCallback(Callback callback),可以向这个类中注册一个Callback(MainActivity),并且SurfaceHold...

1006
上一篇: 【性能优化】Android 开发进阶必经之路!
下一篇: Android利用SurfaceView显示Camera图像爬坑记(二)
网络安全-XG
博客等级 码龄5年 1万+粉丝 2752原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值