废话不多说,直接上代码
1,定义相机类kcamera
package com.kneron.kfaceservice;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.util.Log;
import java.util.List;
/**
* Created by wayen on 18-8-25.
*/
public class kcamera {
public kcamera(Camera.PreviewCallback cb){
mst = new SurfaceTexture(0);
this.mPreviewCb=cb;
}
private Camera.PreviewCallback mPreviewCb;
private final static String TAG="kcamera";
/**
* ASPECT_RATIO_W and ASPECT_RATIO_H define the aspect ratio
* of the Surface. They are used when {@link #onMeasure(int, int)}
* is called.
*/
private final float ASPECT_RATIO_W = 4.0f;
private final float ASPECT_RATIO_H = 3.0f;
/**
* The maximum dimension (in pixels) of the preview frames that are produced
* by the Camera object. Note that this should not be intended as
* the final, exact, dimension because the device could not support
* it and a lower value is required (but the aspect ratio should remain the same).
* See {@link CameraPreview#getBestSize(List, int)} for more information.
*/
private final int PREVIEW_MAX_WIDTH = 640;
/**
* The maximum dimension (in pixels) of the images produced when a
* {@link Camera.PictureCallback#onPictureTaken(byte[], Camera)} event is
* fired. Again, this is a maximum value and could not be the
* real one implemented by the device.
*/
private final int PICTURE_MAX_WIDTH = 640;
/**
* 'camera' is the object that references the hardware device
* installed on your Android phone.
*/
private Camera camera;
/**
* Phone can have multiple cameras, so 'cameraID' is a
* useful variable to store which one of the camera is active.
* It starts with value -1
*/
private int cameraID=-1;
SurfaceTexture mst;
/**
* [IMPORTANT!] The most important method of this Activity: it asks for an instance
* of the hardware camera(s) and save it to the private field {@link #camera}.
*
* @return TRUE if camera is set, FALSE if something bad happens
*/
public boolean setCameraInstance() {
if (this.camera != null) {
// do the job only if the camera is not already set
Log.i(TAG, "setCameraInstance(): camera is already set, nothing to do");
return true;
}
// warning here! starting from API 9, we can retrieve one from the multiple
// hardware cameras (ex. front/back)
if (this.cameraID < 0) {
// at this point, it's the first time we request for a camera
Camera.CameraInfo camInfo = new Camera.CameraInfo();
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
Camera.getCameraInfo(i, camInfo);
if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
// in this example we'll request specifically the back camera
try {
Log.d(TAG, "setCameraInstance(): trying to open camera #" + i);
this.camera = Camera.open(i);
this.cameraID = i; // assign to cameraID this camera's ID (O RLY?)
this.camera.setPreviewCallback(mPreviewCb);
camera.setPreviewTexture(mst);
// int buffersize = 640 * 480* ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
// previewBuffer = new byte[buffersize];
// camera.addCallbackBuffer(previewBuffer);
// camera.setPreviewCallbackWithBuffer(this);
// SurfaceTexture mst = new SurfaceTexture(0);
Camera.Parameters parameters = camera.getParameters();
Camera.Size bestPreviewSize = getBestSize(parameters.getSupportedPreviewSizes(), PREVIEW_MAX_WIDTH);
//Camera.Size bestPictureSize = getBestSize(parameters.getSupportedPictureSizes(), PICTURE_MAX_WIDTH);
parameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
parameters.setPreviewFormat(ImageFormat.NV21); // NV21 is the most supported format for preview frames
parameters.setPictureFormat(ImageFormat.JPEG); // JPEG for full resolution images
try {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
catch (NoSuchMethodError e) {
// remember that not all the devices support a given feature
Log.e(TAG, "setupCamera(): this camera ignored some unsupported settings.", e);
}
camera.setParameters(parameters); // save everything
camera.startPreview();
return true;
} catch (Exception e) {
// something bad happened! this camera could be locked by other apps
Log.e(TAG, "setCameraInstance(): trying to open camera #" + i + " but it's locked", e);
}
}
}
}
// we could reach this point in two cases:
// - the API is lower than 9
// - previous code block failed
// hence, we try the classic method, that doesn't ask for a particular camera
if (this.camera == null) {
try {
//openCameraBegin=System.currentTimeMillis();
Log.d(TAG, "setCameraInstance(): trying to open camera");
this.camera = Camera.open(1);
this.cameraID = 1;
} catch (RuntimeException e) {
// this is REALLY bad, the camera is definitely locked by the system.
Log.e(TAG,
"setCameraInstance(): trying to open default camera but it's locked. "
+ "The camera is not available for this app at the moment.", e
);
return false;
}
}
// here, the open() went good and the camera is available
Log.i(TAG, "setCameraInstance(): successfully set camera #" + this.cameraID);
return true;
}
/**
* [IMPORTANT!] Another very important method: it releases all the resources and the locks
* we created while using the camera. It MUST be called everytime the app exits, crashes,
* is paused or whatever. The order of the called methods are the following:
*
* 1) stop any preview coming to the GUI, if running
* 2) call {@link Camera#release()}
* 3) set our camera object to null and invalidate its ID
*/
public void releaseCameraInstance() {
if (this.camera != null) {
try {
this.camera.stopPreview();
} catch (Exception e) {
Log.i(TAG, "releaseCameraInstance(): tried to stop a non-existent preview, this is not an error");
}
this.camera.setPreviewCallback(null);
this.camera.release();
this.camera = null;
this.cameraID = -1;
Log.i(TAG, "releaseCameraInstance(): camera has been released.");
}
}
/**
* [IMPORTANT!] This is a convenient function to determine what's the proper
* preview/picture size to be assigned to the camera, by looking at
* the list of supported sizes and the maximum value given
* @param sizes sizes that are currently supported by the camera hardware,
* retrived with {@link Camera.Parameters#getSupportedPictureSizes()} or {@link Camera.Parameters#getSupportedPreviewSizes()}
* @param widthThreshold the maximum value we want to apply
* @return an optimal size <= widthThreshold
*/
private Camera.Size getBestSize(List sizes, int widthThreshold) {
Camera.Size bestSize = null;
for (Camera.Size currentSize : sizes) {
boolean isDesiredRatio = ((currentSize.width / ASPECT_RATIO_W) == (currentSize.height / ASPECT_RATIO_H));
boolean isBetterSize = (bestSize == null || currentSize.width > bestSize.width);
boolean isInBounds = currentSize.width <= widthThreshold;
if (isDesiredRatio && isInBounds && isBetterSize) {
bestSize = currentSize;
}
}
if (bestSize == null) {
bestSize = sizes.get(0);
Log.e(TAG, "determineBestSize(): can't find a good size. Setting to the very first...");
}
Log.i(TAG, "determineBestSize(): bestSize is " + bestSize.width + "x" + bestSize.height);
return bestSize;
}
}
2 实现 Camera.PreviewCallback,可以写在你的Activity里面
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
3 使用
mcamera=new kcamera(this);//一般写在oncreat里面即可
boolean ret= mcamera.setCameraInstance();//开启预览
mcamera.releaseCameraInstance();//别忘记关闭