1.注册 SurfaceView实例:
private SurfaceView mainSfCamera;
mainSfCamera = (SurfaceView) findViewById(R.id.main_sf_camera);
2.检测是否存在摄像头:
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "搜索到摄像头硬件", Toast.LENGTH_SHORT).show();
return true;
} else {
Toast.makeText(this, "不具备摄像头硬件", Toast.LENGTH_SHORT).show();
return false;
}
}
3.建立CameraSurfaceHolder工具类
/**
* 相机界面SurfaceView的Holder类
*/
public class CameraSurfaceHolder {
Context context;
SurfaceHolder surfaceHolder;
SurfaceView surfaceView;
SurfaceViewCallback callback = new SurfaceViewCallback();
/**
* 设置相机界面SurfaceView的Holder
* @param context 从相机所在的Activity传入的context
* @param surfaceView Holder所绑定的响应的SurfaceView
* */
public void setCameraSurfaceHolder(Context context, SurfaceView surfaceView) {
this.context = context;
this.surfaceView = surfaceView;
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(callback);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
callback.setContext(context);
}
}
4.在主类中绑定:
CameraSurfaceHolder mCameraSurfaceHolder = new CameraSurfaceHolder();
mCameraSurfaceHolder.setCameraSurfaceHolder(MainActivity.this,mainSfCamera);
5.SurfaceViewCallback 工具类:
/**
* 相机界面SurfaceView的回调类
*/
public final class SurfaceViewCallback implements SurfaceHolder.Callback, Camera.PreviewCallback {
Context context;
static final String TAG = "SYRFACECamera";
FrontCamera mFrontCamera = new FrontCamera();
boolean previewing = mFrontCamera.getPreviewing();
Camera mCamera;
FaceTask mFaceTask;
public void setContext(Context context) {
this.context = context;
}
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
if (previewing) {
mCamera.stopPreview();
Log.i(TAG, "停止预览");
}
try {
mCamera.setPreviewDisplay(arg0);
mCamera.startPreview();
mCamera.setPreviewCallback(this);
Log.i(TAG, "开始预览");
//调用旋转屏幕时自适应
//setCameraDisplayOrientation(MainActivity.this, mCurrentCamIndex, mCamera);
} catch (Exception e) {
}
}
public void surfaceCreated(SurfaceHolder holder) {
//初始化前置摄像头
mFrontCamera.setCamera(mCamera);
mCamera = mFrontCamera.initCamera();
mCamera.setPreviewCallback(this);
//适配竖排固定角度
FrontCamera.setCameraDisplayOrientation((Activity) context, mFrontCamera.getCurrentCamIndex(), mCamera);
Log.i(TAG, "surfaceCreated");
}
public void surfaceDestroyed(SurfaceHolder holder) {
mFrontCamera.StopCamera(mCamera);
Log.i(TAG, "surfaceDestroyed");
}
/**
* 相机实时数据的回调
*
* @param data 相机获取的数据,格式是YUV
* @param camera 相应相机的对象
*/
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (mFaceTask != null) {
switch (mFaceTask.getStatus()) {
case RUNNING:
return;
case PENDING:
mFaceTask.cancel(false);
break;
}
}
mFaceTask = new FaceTask(data, camera);
mFaceTask.execute((Void) null);
//Log.i(TAG, "onPreviewFrame: 启动了Task");
}
}
6.FrontCamera工具类:
/**
* 相机类,相机的调用
*/
public class FrontCamera {
static final String TAG = "Camera";
Camera mCamera;
int mCurrentCamIndex = 0;
boolean previewing;
public void setCamera(Camera camera)
{
this.mCamera = camera;
}
public int getCurrentCamIndex()
{
return this.mCurrentCamIndex;
}
public boolean getPreviewing()
{
return this.previewing;
}
Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {
@Override
public void onShutter() {
}
};
Camera.PictureCallback rawPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
}
};
Camera.PictureCallback jpegPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = null;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Log.i(TAG, "已经获取了bitmap:" + bitmap.toString());
previewing = false;
//需要保存可执行下面
/* new Thread(new Runnable() {
@Override
public void run() {
String filePath = ImageUtil.getSaveImgePath();
File file = new File(filePath);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file, true);
fos.write(data);
ImageUtil.saveImage(file, data, filePath);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();*/
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mCamera.startPreview();//重新开启预览 ,不然不能继续拍照
previewing = true;
}
};
//初始化相机
public Camera initCamera() {
int cameraCount = 0;
Camera cam = null;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();
Log.e(TAG, "cameraCount: " + cameraCount);
previewing = true;
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo);
//在这里打开的是前置摄像头,可修改打开后置OR前置
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
try {
cam = Camera.open(camIdx);
mCurrentCamIndex = camIdx;
} catch (RuntimeException e) {
Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
}
}
}
return cam;
}
/**
* 停止相机
* @param mCamera 需要停止的相机对象
* */
public void StopCamera(Camera mCamera) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
previewing = false;
}
/**
* 旋转屏幕后自动适配(若只用到竖的,也可不要)
* 已经在manifests中让此Activity只能竖屏了
* @param activity 相机显示在的Activity
* @param cameraId 相机的ID
* @param camera 相机对象
*/
public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera)
{
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation)
{
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
{
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
}
else
{
// back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
}
7.FaceTask工具类:
/**
* 单独的任务类。继承AsyncTask,来处理从相机实时获取的耗时操作
*/
public class FaceTask extends AsyncTask{
private byte[] mData;
Camera mCamera;
private static final String TAG = "CameraTag";
//构造函数
FaceTask(byte[] data , Camera camera)
{
this.mData = data;
this.mCamera = camera;
}
@Override
protected Object doInBackground(Object[] params) {
Camera.Parameters parameters = mCamera.getParameters();
int imageFormat = parameters.getPreviewFormat();
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
Rect rect = new Rect(0, 0, w, h);
YuvImage yuvImg = new YuvImage(mData, imageFormat, w, h, null);
try {
ByteArrayOutputStream outputstream = new ByteArrayOutputStream();
yuvImg.compressToJpeg(rect, 100, outputstream);
Bitmap rawbitmap = BitmapFactory.decodeByteArray(outputstream.toByteArray(), 0, outputstream.size());
Log.i(TAG, "onPreviewFrame: rawbitmap:" + rawbitmap.toString());
//若要存储可以用下列代码,格式为jpg
/* BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/fp.jpg"));
img.compressToJpeg(rect, 100, bos);
bos.flush();
bos.close();
mCamera.startPreview();
*/
}
catch (Exception e)
{
Log.e(TAG, "onPreviewFrame: 获取相机实时数据失败" + e.getLocalizedMessage());
}
return null;
}
}
8.别忘了权限申请或targetSdkVersion设置为23以下
<uses-permission android:name="android.permission.CAMERA" />
源码下载地址:https://download.csdn.net/download/qq_30297763/11181177
GitHub地址:https://github.com/xingaijian/surfaceviewcameras