最近项目需求要做录音录像,当时想调用系统的最方便,但是这样app的用户体验会不好,而且系统做的的布局是固定的,就想自己做一个,于是开始百度搬砖,首先安卓不同版本权限不一样,权限就不说,动态获取使用的是easyP,录像嘛,开始有预览功能,这里采用的是自定义的TextureView,搬砖所得,具体也不记得就是试了很多,这个相对来说感觉不错,其中有多出修改,不然会报错,源码如下
public class TextureCameraPreview extends TextureView implements TextureView.SurfaceTextureListener, Camera.PictureCallback, Camera.ShutterCallback {
private Camera mCamera;
private int index = 0;
private OnPictureTakenListener onPictureTakenListener;
private MediaRecorder mMediaRecorder;
private boolean isRecording = false;
private OnStartVideoListener onStartVideoListener;
private SurfaceTexture mSurface;
public TextureCameraPreview(Context context) {
this(context, null);
}
public TextureCameraPreview(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TextureCameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setSurfaceTextureListener(this);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mSurface = surface;
openCamera();
}
private void openCamera() {
// 1.打开相机
if(mCamera==null){
mCamera = getCameraInstance(getContext(), index);
}
if (mCamera != null) {
// 2.设置相机参数
Camera.Parameters parameters = mCamera.getParameters();
// 3.调整预览方向
mCamera.setDisplayOrientation(90);
// 4.设置预览尺寸
int PreviewWidth = 0;
int PreviewHeight = 0;
//这里修改原作者的代码,动态获取分辨率,原来设置是死的会崩
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);//获取窗口的管理器
Display display = wm.getDefaultDisplay();//获得窗口里面的屏幕
// 选择合适的预览尺寸
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
// 如果sizeList只有一个我们也没有必要做什么了,因为就他一个别无选择
if (sizeList.size() > 1) {
Iterator<Camera.Size> itor = sizeList.iterator();
while (itor.hasNext()) {
Camera.Size cur = itor.next();
if (cur.width >= PreviewWidth
&& cur.height >= PreviewHeight) {
PreviewWidth = cur.width;
PreviewHeight = cur.height;
break;
}
}
}
S.e(PreviewWidth+""+PreviewHeight);
parameters.setPreviewSize(PreviewWidth, PreviewHeight); //获得摄像区域的大小
parameters.setPictureSize(PreviewWidth, PreviewHeight);//设置拍出来的屏幕大小
// parameters.setPreviewSize(640, 480); //获得摄像区域的大小
// parameters.setPictureSize(640, 480);//设置拍出来的屏幕大小
// parameters.setPreviewSize(1920, 1080);
// parameters.setPictureSize(1920, 1080);
//原来没有对焦功能,拍出来的画质迷糊看不是很清 parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//1连续对焦
// 5.调整拍照图片方向
if (index == 0)
parameters.setRotation(90);
if (index == 1)
parameters.setRotation(270);
mCamera.setParameters(parameters);
// 6.开始相机预览
try {
mCamera.setPreviewTexture(mSurface);
mCamera.startPreview();
mCamera.cancelAutoFocus();// 2如果要实现连续的自动对焦,这一句必须加上
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getContext(), "Error setting camera preview:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
//原本没有的,当画面变化,重新设置相机,再次对焦
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean b, Camera camera) {
if(b){
openCamera();//实现相机的参数初始化
camera.cancelAutoFocus();//只有加上了这一句,才会自动对焦。
}
}
});
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
releaseCamera();
//原本是true,播放视频修改
return true;
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
public static Camera getCameraInstance(Context context, int i) {
Camera c = null;
try {
c = Camera.open(0);
} catch (Exception e) {
S.e(e.getMessage()+""+e.getCause());
Toast.makeText(context, "相机打开失败", Toast.LENGTH_SHORT).show();
}
return c;
}
public void takePicture(OnPictureTakenListener listener) {
if (listener != null) {
onPictureTakenListener = listener;
if (mCamera != null) {
mCamera.takePicture(this, null, this);
} else {
onPictureTakenListener.onFailed("拍照失败");
}
}
}
public void setZoom(int progress) {
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setZoom((int) (progress * 1.0f / (40 * 100) * 40));
mCamera.setParameters(parameters);
}
}
public void switchCamera(int index) {
if (isRecording) {
stopRecord();
}
releaseCamera();
this.index = index;
openCamera();
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
if (index == 1) {
bitmap = reversalBitmap(bitmap, -1, 1);
}
if (onPictureTakenListener != null) {
onPictureTakenListener.onSuccess(bitmap);
}
// 使拍照结束后重新预览
releaseCamera();
openCamera();
}
private Bitmap reversalBitmap(Bitmap srcBitmap, float sx, float sy) {
Bitmap cacheBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.ARGB_8888);
int w = cacheBitmap.getWidth();
int h = cacheBitmap.getHeight();
Canvas canvas = new Canvas(cacheBitmap);
Matrix matrix = new Matrix();
matrix.postScale(sx, sy);
Bitmap bitmap = Bitmap.createBitmap(srcBitmap, 0, 0, w, h, matrix, true);
canvas.drawBitmap(bitmap, new Rect(0, 0, srcBitmap.getWidth(), srcBitmap.getHeight()), new Rect(0, 0, w, h), null);
return bitmap;
}
@Override
public void onShutter() {
}
public interface OnPictureTakenListener {
void onSuccess(Bitmap bitmap);
void onFailed(String msg);
}
// ---------------- 录像
private boolean initMediaRecorder(String outputPath) {
mMediaRecorder = new MediaRecorder();
if (mCamera != null) {
// 1.解锁并将相机设置daoMediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// 2.设置资源
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// 3.设置CamcorderProfile(需要API级别8或更高版本)
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// 4.设置输出文件
mMediaRecorder.setOutputFile(outputPath);
// 5.准备配置的MediaRecorder
try {
mMediaRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getContext(), "录像配置准备失败", Toast.LENGTH_SHORT).show();
releaseMediaRecorder();
return false;
}
return true;
}
return false;
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
}
}
public void startRecord(String outputPath, OnStartVideoListener listener) {
this.onStartVideoListener = listener;
if (initMediaRecorder(outputPath)) {
new MediaPrepareTask(listener).execute();
} else {
Toast.makeText(getContext(), "开始录制视频失败", Toast.LENGTH_SHORT).show();
}
}
public void stopRecord() {
if (isRecording) {
mMediaRecorder.stop();
releaseMediaRecorder();
mCamera.lock();
if (onStartVideoListener != null)
onStartVideoListener.onStop();
} else {
releaseMediaRecorder();
}
isRecording = false;
}
public boolean isRecording() {
return isRecording;
}
class MediaPrepareTask extends AsyncTask<Void, Void, Boolean> {
OnStartVideoListener listener;
MediaPrepareTask(OnStartVideoListener listener) {
this.listener = listener;
}
@Override
protected Boolean doInBackground(Void... params) {
mMediaRecorder.start();
isRecording = true;
return true;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if (listener != null)
listener.onStart();
}
}
public interface OnStartVideoListener {
void onStart();
void onStop();
}
private MediaPlayer mMediaPlayer;
public void PlayVideo(String path){
//本来想尝试录制好之后,播放一下,试了一下午,没有成功
try {
Uri uri = Uri.parse(path);
mMediaPlayer=MediaPlayer.create(getContext(), uri);
mMediaPlayer.setDataSource(getContext(), uri);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setSurface( new Surface(mSurface));
// try{
// mMediaPlayer.prepare();
// }catch (Exception e){
// e.printStackTrace();
// }
// mMediaPlayer.start();
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mMediaPlayer.start();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public void StopVideo(){
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
在安卓6.0使用,权限要给切记。