Android 相机预览在切换相机时冻结?

2024-02-26

我正在为我的应用程序编写一个自定义相机。使用后置或前置摄像头打开活动时,它工作正常。但我真的很难在活动中切换摄像机。

当我点击切换相机按钮时,预览冻结但什么也没发生。我已经尝试了与相机和预览相关的其他问题中建议的答案和提示,但没有任何效果。

这是我的活动:

public class CameraActivity extends Activity implements SurfaceHolder.Callback {

    //================================================================================
    // Properties
    //================================================================================

    // Tag
    private final String TAG = "CameraActivity";

    // Camera and CameraPreview objects
    private Camera mCamera;

    // SurfaceHolder object
    private SurfaceHolder mSurfaceHolder;
//    private CameraPreview mPreview;

    // ImageButtons
    private ImageButton captureButton;
    private ImageButton camSwitchButton;

    // Picture previewLayout
    FrameLayout previewLayout;
    SurfaceView preview;

    // Current camera is facing FRONT or BACK
    private int currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;

    // Picture taking callback
    private Camera.PictureCallback mPictureCallback;

    //================================================================================
    // Methods
    //================================================================================

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Activity with no notification bar
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        // Set content view
        setContentView(R.layout.activity_camera);

        // Initialize activity and previews
        InitActivity();
        InitPreview();

        // Set onClicks
    }

    /**
     * Initialize activity views
     */
    private void InitActivity() {

        // Create an instance of Camera
        mCamera = GetCameraInstance(currentCameraId);

        // Set the SurfaceView
        preview = (SurfaceView) findViewById(R.id.camera_preview);
        mSurfaceHolder = preview.getHolder();
        mSurfaceHolder.addCallback(this);

    }

    /**
     * Initialize the camera preview
     */
    private void InitPreview() {

        if (mCamera != null) {

            try {
                mCamera.setPreviewDisplay(mSurfaceHolder);
            } catch (IOException e) {
                // log
            }

            mCamera.startPreview();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release(); // release the camera for other applications
            // mCamera = null;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mCamera == null) {
            InitActivity();
            InitPreview();
        }
    }

    /**
     * Get camera instance
     * @return Camera instance (null if doesn't exist)
     */
    private Camera GetCameraInstance(int camid) {

        Camera c = null;

        try {

            c = Camera.open(camid); // attempt to get a Camera instance

            Camera.Parameters campar = c.getParameters();

            // Set auto-focus
            if (getPackageManager().hasSystemFeature("android.hardware.camera.autofocus")) {
                campar.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            }

            c.setParameters(campar);

        }
        catch (Exception e){
            // log
        }

        return c; // returns null if camera is unavailable
    }

    /**
     * Switch the camera from front to back and vica verca
     */
    private void SwitchCamera() {

        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            // mCamera = null;
        }

        //swap the id of the camera to be used
        if (currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
        }
        else currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;

        // Remove the view and re-add it
        ViewGroup rootView = (ViewGroup) preview.getParent();
        rootView.removeView(previewLayout);

        mCamera = GetCameraInstance(currentCameraId);

        InitActivity();

    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        Logger.Log(TAG, "SurfaceCreated");
        InitPreview();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {    
        // Return if no surface found
        if (mSurfaceHolder.getSurface() == null) {
            return;
        }

        // Start preview with new settings
        Camera.Parameters params = mCamera.getParameters();
        boolean isPortrait = IsPortrait();

        // Configure the parameters (so the image is showing correctly)
        ConfigureCameraParameters(params, isPortrait);

        // Start preview
        InitPreview();

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    /**
     * Configure the camer parameters
     * @param cameraParams Camera parameters
     * @param isPortrait Is the camera in portrait mode?
     */
    protected void ConfigureCameraParameters(Camera.Parameters cameraParams, boolean isPortrait) {

        int angle;

        Display display = getWindowManager().getDefaultDisplay();

        // Correct the orientation
        switch (display.getRotation()) {

            case Surface.ROTATION_0: // This is display orientation
                angle = 90; // This is camera orientation
                break;
            case Surface.ROTATION_90:
                angle = 0;
                break;
            case Surface.ROTATION_180:
                angle = 270;
                break;
            case Surface.ROTATION_270:
                angle = 180;
                break;
            default:
                angle = 90;
                break;
        }

        mCamera.setDisplayOrientation(angle);
        mCamera.setParameters(cameraParams);
    }

    /**
     * Check whether the camera is in portrait mode
     * @return True|False
     */
    private boolean IsPortrait() {
        return (getResources().getConfiguration().orientation
                == Configuration.ORIENTATION_PORTRAIT);
    }
}

清单中的权限:

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

如果有人能提供帮助,我真的很感激。


你已经非常接近了,你不需要每次切换相机时都销毁表面视图,你只需要销毁相机会话,然后确保将相机重新连接到表面视图,以便它可以显示。我在 Razr Max 上的前置后置逻辑方面遇到了一些问题,所以我只是将其切换为 1 和 0。

    private void SwitchCamera() {

    if (mCamera != null) {
        mCamera.stopPreview();
        mCamera.release();
         mCamera = null;
    }

    //swap the id of the camera to be used
    if (currentCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        currentCameraId = 0;
    } else  {
        currentCameraId = 1;
    }

    mCamera = GetCameraInstance(currentCameraId);

    InitPreview();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 相机预览在切换相机时冻结? 的相关文章

  • Android Wear:在手持设备上启动服务

    我正在构建一个 Wear 应用程序 它将与手持设备上的 WearableListenerService 进行通信 但是 我想确保当应用程序在手表上启动时服务已启动并运行 我最初的想法是发送意图或广播消息来启动服务 但是 我一直无法弄清楚如何
  • 标记上存在语法错误,需要 AnnotationName - 查询错误

    我收到了令牌语法错误 AnnotationName 预期出现在以下行 query findInBackground new FindCallback
  • ViewPager 显示的第一个片段与 FragmentStatePager 总是错误的

    我正在尝试拥有相同的view pager tabs设计为 PlayStore 5 1 x 这是我的布局
  • 在 Android strings.xml 文件中使用 HREF

    我正在尝试从 strings xml 文件中为 TextView android text 属性分配以下字符串 我无法让链接显示为可点击的超链接 有什么建议么 我尝试过以下技术
  • 将片段部分移出屏幕

    我已经被这个问题难住有一段时间了 我试图将包含在 FrameLayout 中的片段向右移动 以便只有片段的左侧 20 可见 我认为我遇到的问题是父级不会让片段移出其边界 或者我不知道如何移动它 我所尝试的一切只是将片段推到右墙上 然后缩放片
  • 在我授予许可后,表面视图不显示相机

    public View onCreateView LayoutInflater inflater Nullable ViewGroup container Bundle savedInstanceState View view inflat
  • 如何使用 Retrofit 2 和 RxJava 处理分页

    我知道如何处理 Retrofit 响应 但在使用 rx java 处理来自 REST API 的分页时遇到问题 背景 我使用的其余 api 为我提供了以下响应 并在标题中提供了下一页的链接 HTTP 200 OK Allow GET HEA
  • Android EditText默认数字键盘和允许文本[重复]

    这个问题在这里已经有答案了 可能的重复 EditText 默认带有数字键盘 但允许字母字符 https stackoverflow com questions 3544214 edittext with number keypad by d
  • 终端 (Mac) 上的 ndk-build 命令出错

    这是我在 bashrc 中的环境变量设置 export ANDROID SDK AndroidSDK android sdks export ANDROID NDK AndroidNDK android ndk r8d export PAT
  • Android Fragment 中的 SharedPreferences

    我正在尝试读取 Fragment 内的 SharedPreferences 我的代码用于获取任何其他活动中的首选项 SharedPreferences preferences getSharedPreferences pref 0 我收到错
  • 使用 Retrofit 2 添加标头以请求

    我正在尝试发送带有身份验证标头的请求 但服务器似乎无法识别客户端 我用了this https futurestud io tutorials android basic authentication with retrofit教程 并实现了
  • 当我单击 GridView 项时返回 ImageView 实例

    当我点击GridView项时如何返回ImageView实例 我为 ItemClick 创建自定义绑定事件 public class ItemClickSquareBinding MvxBaseAndroidTargetBinding pri
  • 如果从超链接打开,应用程序将启动两次

    我正在开发一个应用程序 可以从多个地方启动 例如日历中的超链接 我在以下场景中面临问题 如果应用程序已启动并在后台运行 并且用户单击本机日历中的事件 超链接来启动应用程序 我的应用程序作为新实例启动两次 在正在运行的应用程序列表中 我可以看
  • 过滤列表视图并获取正确的 onclick 项目

    我有一个列表视图 并且已经实现了过滤 假设我有项目 A B 和 C 如果我在过滤框中输入 B 则只会显示项目 B 它是列表的位置 0 之前位于位置 1 因此 当我调用 onClick 项目时 我得到 id position 0 这导致显示有
  • DOM 中不再存在缓存元素

    就像在类似的问题中一样 我使用appium java 尝试选择元素 在移动应用程序中 我要转到页面 之后有许多元素 android widget ImageView 0 我需要选择 6 个 例如 这样的元素并执行其他步骤 Byt 只能选择一
  • startDrag 方法 已弃用且无法编译程序

    startDrag android content ClipData android view View DragShadowBuilder java lang Object int 已弃用 如何解决这个问题而又不失去对旧版本的兼容性 还有
  • 我收到“循环依赖”Android Dagger Hilt 错误

    我从头开始检查了所有内容 但找不到错误 我找不到错误 可能是什么 我收到以下编译错误 HomeViewModel java 6 error ComponentProcessor MiscError dagger internal codeg
  • 如何在清单文件中添加符合我意图的标志

    我们知道 我们可以使用 java 代码中的 addFlags 方法将一些标志添加到我们的意图中 有什么方法可以将这些标志添加到清单文件本身中 而不是用 java 代码编写 我需要为清单中的一项活动添加 REORDER TO FRONT 标志
  • 如何在运行时检查授予权限?

    In Android M 预览版 用户可以选择特定的应用程序并检索特定的权限 所以我问如何在运行时检查授予权限 您可以使用以下复制的代码https android googlesource com platform frameworks b
  • 切换按钮形状不变

    我正在尝试制作一个带有绿色背景的圆形切换按钮 我用了

随机推荐

  • getBoundingClientRect().top 和 offsetTop 之间的区别?

    getBoundingClientRect top 和 offsetTop 有什么区别 https codepen io anon pen bWZWQg https codepen io anon pen bWZWQg const elem
  • 如何为所有活动设置背景?

    如何为Android应用程序中的所有活动设置背景并保持其宽高比 我在用android windowBackground风格 但我不知道如何保持背景图像的纵横比 有没有唯一的方法可以添加ImageView手动设置所有活动的背景 您也许可以在其
  • 几乎标准模式如何改变标准模式的渲染?

    我能找到的所有文档都表明 几乎标准模式与标准模式的不同之处仅在于表格单元格中图像的对齐方式 这个问题 Internet Explorer 8 和复选框 CSS 问题 https stackoverflow com questions 141
  • Python 是否有相当于 Ruby 字符串插值的函数?

    红宝石示例 name Spongebob Squarepants puts Who lives in a Pineapple under the sea n name 成功的 Python 字符串连接对我来说似乎很冗长 Python 3 6
  • 可以使用相同的密钥签署两个不同的应用程序吗?

    我制作了两个版本的应用程序 一个 大 版本和一个 迷你 精简 版本 我应该使用相同的密钥对这两个签名进行签名吗 或者我应该为每个人使用唯一的密钥进行签名 使用同一密钥签署多个应用程序会产生什么影响 仅当您需要共享数据或其他资源时 请使用相同
  • 未定义参考[重复]

    这个问题在这里已经有答案了 当我编译链接列表的代码时 我收到一堆未定义的引用错误 代码如下 我一直在编译这两个语句 g test cpp 也 g LinearNode h LinearNode cpp LinkedList h Linked
  • Google 字体粗细 300 不起作用

    在 Chrome 或 Chrome Canary 中工作时 无法打开 google fonts open 的 300 字重 我已经尝试过了this https stackoverflow com questions 20525609 fon
  • 如何在 Node.js 中根据 XML 验证 DTD

    如何根据 Node js 中的特定 XML 验证 DTD 我有一个端点 其中包含每个 XML 负载的 DTD 但试图找到一个可以使用 Node 进行模式验证的良好解决方案 这是一篇旧文章 但现在我们可以这样做节点Libxml https w
  • System.BadImageFormatException:无法加载文件或程序集[重复]

    这个问题在这里已经有答案了 C Windows Microsoft NET Framework64 v4 0 30319 gt InstallUtil exe C PRODUKCIJA D ebug DynamicHtmlTool exe
  • 将 WasapiLoopbackCapture wav 音频流转换为 MP3 文件

    我能够在 WasapiLoopbackCapture naudio 的帮助下捕获由扬声器生成的系统音频 但问题是它捕获 wav 文件并且 wav 文件的大小非常大 几乎 10 到 15 MB 分钟 我必须捕获 2 3 小时的音频 这太长了
  • 我不应该将接口作为 const 传递吗?

    我最近 又 遇到了将接口传递为时的 Delphi 编译器代码生成错误const https stackoverflow com a 7640979 12597泄漏参考 如果您的方法被声明为传递接口变量 则会发生这种情况const e g p
  • 链接的属性 target="_newtab"

    什么是 newtab 中的目标属性值HTML a 标签 我找不到有关浏览器兼容性的信息 它适用于所有现代浏览器吗 如果在浏览器选项中用户设置为在新窗口而不是在新选项卡中打开链接 它将如何工作 这个值是否在任何地方描述过HTML标准 你确定
  • 使用 pyplot.imshow 时禁用 MatPlotLib 警告

    第一次来这里 当我使用时 我收到以下警告pyplot imshow功能 使用 RGB 数据将输入数据裁剪到 imshow 的有效范围 浮点数为 0 1 整数为 0 255 根据我的数据 我知道这是完全预期的行为 如何关闭此警告 我努力了 i
  • 在字符串列表中搜索字符串的有效方法?

    我有一个字符串列表 需要查找哪些字符串与给定的输入值匹配 对我来说 存储此字符串列表并能够搜索它的最有效方法 内存与执行速度 是什么 字符串列表的启动和加载并不重要 但搜索的响应时间很重要 我应该使用 List 或 HashSet 还是只是
  • 使用 python 启动通过 chcp 65001 预先激活的控制台窗口

    我使用 python 库将 Unicode 字符打印到 Windows 控制台 如果我调用库中打印出 Unicode 字符的函数 它将引发异常 charmap codec can t encode characters 这就是我试图解决该错
  • ModuleNotFoundError:没有名为“flask”的模块

    阅读完这篇文章的标题后 不要尝试先复制 因为这里的内容可能会以不同的方式被问到 顺便说一句 我对 python 很陌生 现在为了工作需要开始学习 这是我的依赖项 virtualenv version gt 15 0 2 pip versio
  • “Message”:“此请求的授权已被拒绝。” OWIN中间件

    我将基于令牌的身份验证添加到我的 OWIN 中间件中 并且可以生成令牌 但在使用具有授权属性的 API 调用的令牌时 我总是收到 此请求的授权已被拒绝 尽管没有 Authorize 属性 但它工作正常 这是我的startup cs 和控制器
  • iOS,通过代码锁定设备

    出于测试目的 制作本地通知的屏幕截图 我需要能够从代码 测试代码或应用程序代码 锁定设备 模拟器 我从这里查看了几个答案 GSEventLockDevice 但它们很旧并且不适合我 XCUIDevice 中有一个私有方法 因此您可以使用它锁
  • Three.js - 如何检查对象是否位于球体后面(不可见)

    我有一个球体 球体 表面有对象 引脚 并且带有 DOM 元素 标签 这些元素是从引脚位置到 2d 世界计算得出的 我的问题是 当图钉位于地球后面 通过鼠标拖动或动画 时 我需要隐藏 DOM 中的标签 以便在没有图钉的情况下文本标签不可见 我
  • Android 相机预览在切换相机时冻结?

    我正在为我的应用程序编写一个自定义相机 使用后置或前置摄像头打开活动时 它工作正常 但我真的很难在活动中切换摄像机 当我点击切换相机按钮时 预览冻结但什么也没发生 我已经尝试了与相机和预览相关的其他问题中建议的答案和提示 但没有任何效果 这