android中,通过相机获取预览界面的需求似乎很变态,好像也没有什么使用场景。但是,有一个场景需要获取预览界面的图像,就是扫码,比如微信,支付宝的扫一扫,就是需要获取预览界面的图像数据的。

实现逻辑比较简单,不过肯定比打开系统相机要麻烦一点的。

下面简单说一下实现步骤:

  1. 实例化一个SurfaceView
  2. surfaceCreated()回调中去实例化Camera对象,去自动对焦。
  3. onAutoFocus()回调中去调用camera.takePicture(null,null,callback);
  4. 在第3步的callback里面去获取预览图像数据int data[]
  5. (可选)将获取的数据换成成文件。
  6. (可选)将该文件对象加载成bitmap对象。
  7. 在不使用的使用释放相机资源。

代码细节:

  1. 清单文件:
    <uses-feature android:name="android.hardware.camera" />    <uses-feature android:name="android.hardware.camera.autofocus" />    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.CAMERA" />    <uses-permission android:name="android.permission.RECORD_AUDIO" />
  1. java代码:
package com.python.cat.testgradle;import android.Manifest;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.hardware.Camera;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.widget.Button;import android.widget.FrameLayout;import android.widget.Toast;import com.apkfuns.logutils.LogUtils;import com.google.zxing.BinaryBitmap;import com.google.zxing.ChecksumException;import com.google.zxing.FormatException;import com.google.zxing.NotFoundException;import com.google.zxing.RGBLuminanceSource;import com.google.zxing.Result;import com.google.zxing.common.GlobalHistogramBinarizer;import com.google.zxing.qrcode.QRCodeReader;import com.yanzhenjie.permission.Action;import com.yanzhenjie.permission.AndPermission;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.Arrays;import java.util.List;public class UseCameraActivity extends Activity {    private Activity get() {        return this;    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_asome);        setTitle(getClass().getSimpleName());        final FrameLayout frameLayout = findViewById(R.id.prev_content_layout);        Button btn = findViewById(R.id.start_camera_preview);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                AndPermission.with(get())                        .permission(Manifest.permission.CAMERA,                                Manifest.permission.WRITE_EXTERNAL_STORAGE                        )                        .onDenied(new Action() {                            @Override                            public void onAction(List permissions) {                                LogUtils.e("error....." + permissions);                            }                        })                        .onGranted(new Action() {                            @Override                            public void onAction(List permissions) {                                LogUtils.w("you can do..");                                ScanView scanView = new ScanView(get());                                frameLayout.removeAllViews();                                frameLayout.addView(scanView);                            }                        }).start();            }        });    }    static class ScanView extends SurfaceView implements SurfaceHolder.Callback,            Camera.AutoFocusCallback {        private Camera mCamera;        private final File fileImg;        private ScanView self;        public ScanView(Context context) {            super(context);            fileImg = new File(context.getCacheDir(), "prev_view.jpg");            SurfaceHolder mHolder = getHolder();            self = this;            mHolder.addCallback(this);            // deprecated setting, but required on Android versions prior to 3.0            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        }        @Override        public void onAutoFocus(boolean success, Camera camera) {            LogUtils.w("auto focus..." + success);            if (mCamera != null) {                mCamera.takePicture(null, null, null, new Camera.PictureCallback() {                    @Override                    public void onPictureTaken(byte[] data, Camera camera) {                        mCamera.cancelAutoFocus();                        mCamera.stopPreview(); // 拿到数据就停止!!!                        LogUtils.w("========data========");                        LogUtils.w("----------data-----------------");//                        camera.startPreview();                        File pictureFile = fileImg;                        if (pictureFile == null) {                            LogUtils.e("Error creating media file, check storage permissions: " +                                    null);                            return;                        }                        if (data == null) {                            return;                        }                        try {                            LogUtils.d(data);                            FileOutputStream fos = new FileOutputStream(pictureFile);                            fos.write(data);                            fos.close();                            LogUtils.e("save preview complete###!!!");                            LogUtils.e("save preview complete###!!!" + pictureFile);                            BitmapFactory.Options options = new BitmapFactory.Options();                            options.inJustDecodeBounds = true;                            BitmapFactory.decodeFile(pictureFile.getAbsolutePath(), options);                            options.inJustDecodeBounds = false;                            int outWidth = options.outWidth;                            int outHeight = options.outHeight;                            if (outWidth >= getWidth() * 2) {                                options.inSampleSize = outWidth / getWidth();                            }                            if (outHeight >= getHeight() * 2) {                                options.inSampleSize = outHeight / getHeight();                            }                            Bitmap bmp = BitmapFactory.decodeFile(pictureFile.getAbsolutePath(), options);                            Result result = parseInfoFromBitmap(bmp);                            if (result != null) {                                Toast.makeText(getContext(), "INFO:" + result.getText(), Toast.LENGTH_SHORT).show();                                LogUtils.w("解析成功:" + result);                            } else {                                LogUtils.e("再次尝试中....");                                mCamera.startPreview();                                mCamera.autoFocus(self);                                // todo:这里也可以做最大重试次数的限制...                            }                        } catch (Exception e) {                            LogUtils.e("Error accessing file: " + e.getMessage());                        }                    }                });            }        }        public Result parseInfoFromBitmap(Bitmap bitmap) {            int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];            bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());            LogUtils.w("### pixels dest==" + Arrays.toString(pixels));            RGBLuminanceSource source = new RGBLuminanceSource(bitmap.getWidth(),                    bitmap.getHeight(), pixels);            GlobalHistogramBinarizer binarizer = new GlobalHistogramBinarizer(source);            BinaryBitmap image = new BinaryBitmap(binarizer);            Result result = null;            try {                result = new QRCodeReader().decode(image);                return result;            } catch (NotFoundException e) {                e.printStackTrace();                Toast.makeText(getContext(), "非二维码图片,不能解析", Toast.LENGTH_SHORT).show();            } catch (ChecksumException e) {                e.printStackTrace();            } catch (FormatException e) {                e.printStackTrace();            }            return null;        }        @Override        public void surfaceCreated(SurfaceHolder holder) {            LogUtils.e("x surfaceCreated.. #####");            try {                mCamera = Camera.open();                mCamera.setPreviewDisplay(holder);                mCamera.setDisplayOrientation(90);                Camera.Parameters parameters = mCamera.getParameters();//                parameters.setPictureSize(1600, 1200);//                parameters.setPreviewSize(640, 480);                mCamera.setParameters(parameters);                mCamera.startPreview();                mCamera.autoFocus(this);                LogUtils.e("surfaceCreated.. #####");            } catch (IOException e) {                LogUtils.e("Error setting camera preview: " + e.getMessage());            }        }        @Override        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {            LogUtils.w("--change-");        }        @Override        public void surfaceDestroyed(SurfaceHolder holder) {            LogUtils.w("destroy--");            if (mCamera != null) {                mCamera.cancelAutoFocus();                mCamera.stopPreview();                mCamera.release();            }        }    }}
  1. 布局文件:
<RelativeLayout 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"    tools:context=".UseCameraActivity">    <Button        android:id="@+id/start_camera_preview"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:text="@string/start_camera_preview" />    <FrameLayout        android:id="@+id/prev_content_layout"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_above="@id/start_camera_preview">FrameLayout>RelativeLayout>
  1. gradle配置(可选):
implementation 'com.yanzhenjie:permission:2.0.0-rc4' // 运行时权限语法糖implementation 'com.google.zxing:core:3.3.1' // zxing 解析二维码图片

嗯,以上就是获取相机预览图像数据的代码了。不过,这里用的Camera接口是过时的了,不建议使用。不过可以运行。我目前的compileSdkVersion=26

就酱咯。 完整app代码也许有的吧。

=======

update: 关于Camera2,我选择放弃….

官方的说法是:

The android.hardware.camera2 package provides an interface to individual camera devices connected to an Android device. It replaces the deprecated Camera class.


This package models a camera device as a pipeline, which takes in input requests for capturing a single frame, captures the single image per the request, and then outputs one capture result metadata packet, plus a set of output image buffers for the request. The requests are processed in-order, and multiple requests can be in flight at once. Since the camera device is a pipeline with multiple stages, having multiple requests in flight is required to maintain full framerate on most Android devices.

反正是看懂了一句话,就是用来替代Camera的。

但是,真的很麻烦。我没有找到中文的,可以直接运行的案例,找到了两个外国人写的博客,里面给了完整的代码。不过估计不能直接访问。我把拷贝到我的项目里面去了。可以直接运行

完整app代码
因为每一篇代码都很长,我就不贴出来了,说一下路径。

  1. com.python.cat.testgradle.MainActivity.java[由于这个原始代码没有加动态权限申请,我手动添加了一下…]

  2. com.python.cat.testgradle.AndroidCameraApi.java
    我给的是我代码的路径,以及原始链接。


不清楚是出于什么考虑,camera2里面比camera多了好几类,复杂度也提升了不少。有需要的可以研究一下。上手难度大于camera。(目前我还是一头雾水,对于camera2)。

中文的找到一个:这个我并没有去下载运行验证,不过看博客里面写的挺多的。

更多相关文章

  1. Androidi性能优化之Java代码优化(摘自Android性能优化一书)
  2. 通过Python 获取Android设备信息的轻量级框架
  3. 9个非常棒的Android代码编辑器 移动开发者的最爱
  4. 星云精准测试对安卓底层驱动代码的测试案例分析
  5. Android(安卓)Studio Jni开发(二)实现Native调用java方法和Native
  6. android 取消标题栏出错,程序崩溃的问题
  7. 几行代码,让你的app动感起来--Android(安卓)Design Support Libra
  8. 初学android-调用百度api显示地图(出现显示网格问题)
  9. [置顶] android 多媒体和相机详解六

随机推荐

  1. mysql 5.7.17 安装配置方法图文教程(ubunt
  2. windows无法启动MySQL服务报错1067的解决
  3. mysql 5.7.17 winx64安装配置图文教程
  4. mysql 5.7.17 安装配置方法图文教程(windo
  5. Ubuntu16.04 server下配置MySQL,并开启远
  6. mysql 5.7.17 winx64安装配置方法图文教
  7. mysql免安装没有任何root权限
  8. 浅谈mysql数据库中的换行符与textarea中
  9. MySQL实时监控工具orztop的使用介绍
  10. MySQL基础教程之IN的用法详解