专栏首页Phoenix的Android之旅教你做一个后台相机

教你做一个后台相机

做过相机的同学都知道,Camera需要一个SurfaceView来承载预览的输出流,SurfaceView的特性限制了它必须要有一个可见的View才能够使用。 所以如果我们要做一个不可见的相机有什么办法呢?

初阶黑科技

首先可以想到的是我们可以用一个 1*1 像素的SurfaceView来承载输出流。又或者我们用一个透明的View来承载SurfaceView。 网上搜一下可以找到很多这个方案的实现,

但是! 这意味着但跟我们的app退出到后台的时候,Camera就不能够拍照了!

那么有没有更好的解决方案呢? 当然有!

高阶黑科技

此时我们要介绍一个平时用的少的类,SurfaceTexture。 Camera提供了两个方法来设置预览界面,分别是

public native final void setPreviewSurface(Surface surface) throws IOException;
public native final void setPreviewTexture(SurfaceTexture surfaceTexture) throws IOException;

当用SurfaceTexture作为预览的输出流承载的时候,其实是不需要一个可见的View的。 这提供了一个思路,可以在Service里用它来实现后台拍照的功能。

如何用呢

我们假设一个需求,用户的手机有锁屏密码,他的手机丢失了以后被别人尝试用去解锁,当然别人解锁的话肯定会失败,那么我们可以在他解锁失败的时候启动相机服务,然后用前置摄像头拍照。当我们拿到拍下来的相片后就可以通过各种方式回传给用户了。 这种场景下我们的应用肯定不会在前台出现,所以我们只能通过Service的方式来实现。

首先是解锁的监听

这部分很简单,我们可以继承并重写 DeviceAdminReceiver 来实现。这是一个系统提供的用来监听用户密码状态的类,具体用法可以参考后面给出的demo。

然后是Camera

使用Camera的话都需要先获取硬件Camera并初始化相关的参数, 这里给出demo代码

private Camera getCamerInstance() {
    android.hardware.Camera c = null;

    if(mCamera != null) {
        return mCamera;
    }

    int cameraNum = android.hardware.Camera.getNumberOfCameras();
    Log.d(TAG, "camera number: " + cameraNum);
    try {
        c = android.hardware.Camera.open();
        mCameraId = android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK;
    } catch (Exception e) {
        Log.e(TAG, "initiate Camera failed");
        e.printStackTrace();
    }
    return c;
}

然后我们需要设置一个SurfaceTexture,

mTexture = new SurfaceTexture(0);
try {
    mCamera.setPreviewTexture(mTexture);
    mCamera.startPreview();
} catch (IOException e) {
    Log.e(TAG, "initiate camera failed, e: " + e.getMessage());
}

之后就可以通过Camera的takePicture()来获取相机输出流啦~~ 完整的实现代码已经上传到GitHub

本文分享自微信公众号 - Android每日一讲(gh_f053f29083b9),作者:Phoenix

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-03-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android广播发送流程深度分析

    备注:这个方法在6.0之后移到了 BroadQueue 类中, AMS 的代码也有相应的调整

    PhoenixZheng
  • Java 单例的五种写法

    单例的目的是为了保证某个类只实例化一个对象。对于我们来说,理解这些单例写法的不同点,最好的方法是明白他们在什么情况下会失效。

    PhoenixZheng
  • 你不知道的Interface的骚操作

    "难道面试不顺利?"小A心想。于是问小呼都问了什么。小呼说,面试官问了个奇怪的问题,

    PhoenixZheng
  • Untiy Native Render Plugin在VR中的绘制(二): 透明排序

    逍遥剑客
  • 视频直播技术--Android视频采集(Camera1)

    今天为大家介绍一下使用Camera1进行视频采集。之前我写过一篇文章介绍的是Camera2进行视频采集。那么有人会问,为什么有了Camera2还要介绍Camer...

    音视频_李超
  • linux系统编程之信号(四):信号的捕捉与sigaction函数

    一、内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复...

    s1mba
  • SAS-如何找出数据集超长变量及观测,并自动进行变量的拆分...

    前段时间有人给小编提了一个需求,找出数据集中长度超过200字节的变量,并对变量进行拆分...这个需求当然不难,但是还是分享给大家~主要最近没写啥程序,也就没学到...

    Setup
  • Android Camera SurfaceView 预览拍照

    Android使用 Camera API + SurfaceView 方式进行预览拍照。

    glumes
  • 【LeetCode】2. Add Two Numbers

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    韩旭051
  • 跟我学 systemd

    跟我学 systemd 摘要 我的系列文档 Netkiller Architect 手札Netkiller Developer 手札Netkiller PHP ...

    netkiller old

扫码关注云+社区

领取腾讯云代金券