1.思路
一.通过android的Camera.setPreviewCallback(PreviewCallback cb)监听回调.
二.此回调函数public void onPreviewFrame(byte[] data, Camera camera)每回调一次就是获取到摄像头的一帧原始数据即data字节数组。
三.这个字节数组经过YuvImage类包装压缩成特定类型图片。
2.代码实现
一.权限
<uses-permission android:name="android.permission.CAMERA"/>
二.布局
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.yuncai.menjin.camera_demo.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="200dp"
android:layout_height="200dp">
<TextureView
android:id="@+id/texture_view"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="TextureView(摄像头预览)"
android:textColor="#f00"
android:textSize="10sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="200dp"
android:layout_height="200dp">
<ImageView
android:id="@+id/iv_pic"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="right"
android:src="@mipmap/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="ImageView(视频帧数据预览)"
android:textColor="#f00"
android:textSize="10sp" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="bottom"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/btn_takePic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取视频帧数据" />
</LinearLayout>
</merge>
三.java实现代码
package com.yuncai.menjin.camera_demo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener {
private TextureView textureView;
private ImageView ivPic;
private Button btnTakePic;
private Camera mCamera;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
initListener();
}
private void initListener() {
textureView.setSurfaceTextureListener(this);
btnTakePic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addCallBack();
}
});
}
private void initData() {
int numberOfCameras = Camera.getNumberOfCameras();// 获取摄像头个数
if(numberOfCameras<1){
Toast.makeText(this, "没有相机", Toast.LENGTH_SHORT).show();
finish();
return;
}
}
private void initView() {
textureView = (TextureView) findViewById(R.id.texture_view);
// textureView.setRotation(0); // // 设置预览角度,并不改变获取到的原始数据方向(与Camera.setDisplayOrientation(0)相同)
ivPic = (ImageView) findViewById(R.id.iv_pic);
btnTakePic = (Button) findViewById(R.id.btn_takePic);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
// 打开相机 0后置 1前置
mCamera = Camera.open(0);
if (mCamera != null) {
// 设置相机预览宽高,此处设置为TextureView宽高
Camera.Parameters params = mCamera.getParameters();
params.setPreviewSize(width, height);
// 设置自动对焦模式
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(params);
}
try {
// mCamera.setDisplayOrientation(0);// 设置预览角度,并不改变获取到的原始数据方向
// 绑定相机和预览的View
mCamera.setPreviewTexture(surface);
// 开始预览
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void addCallBack() {
if(mCamera!=null){
mCamera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Size size = camera.getParameters().getPreviewSize();
try{
YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
if(image!=null){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream);
Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
ivPic.setImageBitmap(bmp);
stream.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
});
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
}
3.效果