利用手机自带照相camera,显示在surfaceview上,然后就进行抓怕和录制
一、在surfaceview上显示与拍照、录制,需要考虑以下几点
1、参数设置顺序(特别是录制时,如果参数设置的顺序有误,无法正常录制)
2、手机支持的预览、拍照、录制像素设置(图像模糊、录像花屏)
3、其他参数设置必须符合当前手机
4、摄像头显示时的旋转角度
5、手机支持的格式设置
<LinearLayout 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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical" >
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="300dp"
android:layout_height="300dp" />
<Button
android:id="@+id/changge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="后置摄像头" />
<Button
android:id="@+id/preview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="预览" />
<Button
android:id="@+id/capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="抓拍" />
<Button
android:id="@+id/record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始录制" />
</LinearLayout>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
package com.chenhan.cameratest;
import java.io.File;
import java.io.FileOutputStream;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class LocalMedia implements Callback, PreviewCallback
{
private Camera.Parameters mParameters = null;
@SuppressLint("InlinedApi")
private int mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
private Camera camera;
private SurfaceHolder surfaceHolder;
private int width = 1280;
private int height = 720;
private Activity activity;
private MediaRecorder mediaRecorder;
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public LocalMedia(Activity activity, SurfaceView surfaceView, int cameraId)
{
this.activity = activity;
this.mCameraId = cameraId;
surfaceHolder = surfaceView.getHolder();
surfaceHolder.setFixedSize(width, height);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(this);
//startPreview();
}
public Camera getCamera()
{
return camera;
}
public int getCameraId()
{
return mCameraId;
}
public void startPreview()
{
System.out.println("hhhh");
if (camera != null)
{
camera.startPreview();
System.out.println("cccc");
}
}
public void stopPreview()
{
if (camera != null)
{
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
}
@SuppressLint("NewApi")
@Override
public void surfaceCreated(SurfaceHolder holder)
{
try
{
//if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK)
//{
//camera = Camera.open();
//}
//else
//{
camera = Camera.open(mCameraId);
//}
if (camera != null)
{
/*
* List<Size> sizes =
* camera.getParameters().getSupportedPreviewSizes(); for(int i
* = 0; i < sizes.size(); i++) { Log.e("Preview", "w = " +
* sizes.get(i).width + ";h = " + sizes.get(i).height); }
*/
/*
* List<Size> sizes2 =
* camera.getParameters().getSupportedPictureSizes(); for(int i
* = 0; i < sizes2.size(); i++) { Log.e("Picture", "w = " +
* sizes2.get(i).width + ";h = " + sizes2.get(i).height); }
*/
camera.setPreviewDisplay(surfaceHolder);
camera.setDisplayOrientation(getDispalyOritation(activity,
mCameraId));
mParameters = camera.getParameters();
mParameters.setPreviewSize(1280, 720);
mParameters.setPictureSize(640, 480);
mParameters.setPreviewFormat(ImageFormat.YV12);
camera.setParameters(mParameters);
camera.setPreviewCallback(this);
//startPreview();
System.out.println("bbbb");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
@SuppressLint("NewApi")
public void setCameraId(int camreaId)
{
try
{
camera = Camera.open(camreaId);
if (camera != null)
{
camera.setPreviewDisplay(surfaceHolder);
camera.setDisplayOrientation(getDispalyOritation(activity,
mCameraId));
mParameters = camera.getParameters();
mParameters.setPreviewSize(1280, 720);
mParameters.setPictureSize(640, 480);
mParameters.setPreviewFormat(ImageFormat.YV12);
camera.setParameters(mParameters);
camera.setPreviewCallback(this);
startPreview();
}
}
catch (Exception e)
{
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
if (camera != null)
{
camera.setPreviewCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
}
@Override
public void onPreviewFrame(byte[] data, Camera camera)
{
}
public void takePicture()
{
camera.takePicture(mshutter, null, MJpeg);
}
public Camera.PictureCallback MJpeg = new Camera.PictureCallback()
{
@SuppressLint("InlinedApi")
@Override
public void onPictureTaken(byte[] data, Camera camera)
{
try
{
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix matrix = new Matrix();
matrix.postRotate(getDispalyOritation(activity, mCameraId));
mParameters.setPreviewFormat(ImageFormat.YV12);
bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), matrix, true);
String jpgFile = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/a.jpg";
File file = new File(jpgFile);
FileOutputStream fos = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.JPEG, 100, fos);
if (camera != null)
{
camera.startPreview();
}
fos.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
public Camera.ShutterCallback mshutter = new Camera.ShutterCallback()
{
@Override
public void onShutter()
{
}
};
@SuppressLint("NewApi") public void startRecord()
{
mediaRecorder = new MediaRecorder();
if (camera != null)
{
mediaRecorder.setCamera(camera);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
// 选择当前终端适合的预览size
/*
* List<Size> sizes1 =
* camera.getParameters().getSupportedVideoSizes(); for(int i = 0; i
* < sizes1.size(); i++) { Log.e("Video", "w = " +
* sizes1.get(i).width + ";h = " + sizes1.get(i).height); }
*/
mediaRecorder.setVideoSize(width, height);// 设置分辨率 防止录制的视频出现花屏
// mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setOrientationHint(getDispalyOritation(activity,
mCameraId));
mediaRecorder.setOutputFile(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/b.mkv");
/*
* mediaRecorder
* .setOutputFile(Environment.getExternalStorageDirectory()
* .getAbsolutePath() + "/b.mkv");
*/
try
{
camera.setDisplayOrientation(getDispalyOritation(activity,
mCameraId));
camera.unlock();
mediaRecorder.prepare();
mediaRecorder.start();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public void stopRecord()
{
if (mediaRecorder != null)
{
try
{
mediaRecorder.stop();
mediaRecorder.release();
mediaRecorder = null;
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@SuppressLint("NewApi")
private int getDispalyOritation(Activity activity, int cameraId)
{
int degrees = activity.getWindowManager().getDefaultDisplay()
.getRotation();
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
{
degrees = getDisplayFrontRotation(degrees);
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
}
else
{
degrees = getDisplayBackRotation(degrees);
result = (info.orientation - degrees + 360) % 360;
}
return result;
}
private int getDisplayBackRotation(int degrees)
{
switch (degrees)
{
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 190;
default:
break;
}
return 0;
}
private int getDisplayFrontRotation(int degrees)
{
switch (degrees)
{
case Surface.ROTATION_0:
return 180;
case Surface.ROTATION_90:
return 270;
case Surface.ROTATION_180:
return 0;
case Surface.ROTATION_270:
return 90;
default:
break;
}
return 0;
}
}
package com.chenhan.cameratest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener
{
private SurfaceView surfaceView;
private Button changge, preview, capture, record;
private LocalMedia surfaceCallback;
private boolean startPreview = false;
private boolean recordPreview = false;
private boolean isBack = true;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initSurface();
}
private void initView()
{
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceView.setOnClickListener(this);
changge = (Button) findViewById(R.id.changge);
changge.setOnClickListener(this);
preview = (Button) findViewById(R.id.preview);
preview.setOnClickListener(this);
capture = (Button) findViewById(R.id.capture);
capture.setOnClickListener(this);
record = (Button) findViewById(R.id.record);
record.setOnClickListener(this);
}
@SuppressLint("InlinedApi")
private void initSurface()
{
surfaceCallback = new LocalMedia(this, surfaceView, Camera.CameraInfo.CAMERA_FACING_BACK);
}
@TargetApi(Build.VERSION_CODES.GINGERBREAD) @SuppressLint("InlinedApi")
@Override
public void onClick(View v)
{
// TODO 自动生成的方法存根
switch (v.getId())
{
case R.id.changge:
if (startPreview)
{
if (isBack)
{
changge.setText("前置摄像头");
surfaceCallback.stopPreview();
surfaceCallback.setCameraId(Camera.CameraInfo.CAMERA_FACING_FRONT);
}
else
{
changge.setText("后置摄像头");
surfaceCallback.stopPreview();
surfaceCallback.setCameraId(Camera.CameraInfo.CAMERA_FACING_BACK);
}
isBack = !isBack;
}
else
{
Toast.makeText(this, "请先预览", Toast.LENGTH_SHORT).show();
}
break;
case R.id.preview:
Log.e("aaaaaaaaa", "aaaaaaa");
if (!startPreview)
{
//surfaceCallback = new LocalMedia(this, surfaceView, Camera.CameraInfo.CAMERA_FACING_BACK);
surfaceCallback.startPreview();
preview.setText("停止");
}
else
{
surfaceCallback.stopPreview();
preview.setText("播放");
}
startPreview = !startPreview;
break;
case R.id.capture:
surfaceCallback.getCamera().takePicture(surfaceCallback.mshutter,
null, surfaceCallback.MJpeg);
break;
case R.id.record:
if (!recordPreview)
{
record.setText("录制中");
surfaceCallback.startRecord();
}
else
{
record.setText("录制结束");
Toast.makeText(this, "停止录制", Toast.LENGTH_SHORT).show();
surfaceCallback.stopRecord();
}
recordPreview = !recordPreview;
break;
default:
break;
}
}
}