基本实现了拍照,录制视频,前后摄像头切换的功能,可以转屏,聚焦
源码:https://gitee.com/lyc96/android_video
1.activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="cn.chenlove.video2.MainActivity"> <SurfaceView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/surfaceView"/> <ImageView android:id="@+id/btn" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginRight="50dp" android:layout_height="60dp" android:layout_width="60dp" android:scaleType="centerCrop" android:src="@drawable/video1"/> <ImageView android:id="@+id/camera" android:layout_alignParentBottom="true" android:layout_marginLeft="50dp" android:layout_height="60dp" android:layout_width="60dp" android:layout_marginBottom="6dp" android:scaleType="centerCrop" android:src="@drawable/camera"/> <ImageView android:id="@+id/change" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_height="60dp" android:layout_width="60dp" android:layout_marginBottom="6dp" android:scaleType="centerCrop" android:src="@drawable/change"/> </RelativeLayout>
2.MainActivity
package cn.chenlove.video2; import android.os.Bundle; import android.os.Environment; //import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.widget.ImageView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private static final String TAG = "PlayActivity"; private SurfaceView surfaceView; private CameraUtils cameraUtils; private String path, name; private ImageView btn; private ImageView camera; private ImageView change; int x = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); Log.d(TAG, "onCreate: "); getSupportActionBar().hide(); btn = (ImageView) findViewById(R.id.btn); camera = (ImageView) findViewById(R.id.camera); change = (ImageView) findViewById(R.id.change); surfaceView = (SurfaceView) findViewById(R.id.surfaceView); cameraUtils = new CameraUtils(); cameraUtils.create(surfaceView, this); path = Environment.getExternalStorageDirectory().getAbsolutePath(); name = "Video"; btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (x == 0) { // cameraUtils.changeCamera(); cameraUtils.startRecord(path, name); btn.setImageResource(R.drawable.video); x = 1; } else if (x == 1) { cameraUtils.stopRecord(); btn.setImageResource(R.drawable.video1); x=0; } } }); camera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { cameraUtils.takePicture(path, "name.png"); } }); change.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { cameraUtils.changeCamera(); } }); } @Override protected void onResume() { super.onResume(); Log.d(TAG, "onResume: "); } @Override protected void onPause() { super.onPause(); Log.d(TAG, "onPause: "); } @Override protected void onStop() { super.onStop(); Log.d(TAG, "onStop: "); cameraUtils.stop(); } @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy: "); cameraUtils.destroy(); } }
3.CameraUtils
package cn.chenlove.video2; import android.content.Context; import android.hardware.Camera; import android.media.MediaRecorder; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import static android.content.ContentValues.TAG; /** * Created by guoxw on 2017/10/31. * <!- 实现拍照,录像: 并保存图片,视频到本地></!-> */ public class CameraUtils { private MediaRecorder mediaRecorder; private Camera camera; /*** 标识当前是前摄像头还是后摄像头 back:0 front:1*/ private int backOrFtont = 0; private SurfaceHolder.Callback callback; private Context context; private SurfaceView surfaceView; /***录制视频的videoSize*/ private int height, width; /***photo的height ,width*/ private int heightPhoto, widthPhoto; public void create(SurfaceView surfaceView, Context context) { this.context = context; this.surfaceView = surfaceView; surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.setKeepScreenOn(true); callback = new SurfaceHolder.Callback() { public void surfaceCreated(SurfaceHolder holder) { camera = Camera.open(); getVideoSize(); mediaRecorder = new MediaRecorder(); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { doChange(holder); focus(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { camera.release(); camera = null; } } }; surfaceView.getHolder().addCallback(callback); } private void doChange(SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); camera.setDisplayOrientation(90); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } /** * 切换摄像头 */ public void changeCamera() { int cameraCount = 0; Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); cameraCount = Camera.getNumberOfCameras(); for (int i = 0; i < cameraCount; i++) { Camera.getCameraInfo(i, cameraInfo); if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT && backOrFtont == 0) { camera.stopPreview(); camera.release(); camera = null; camera = Camera.open(i); try { camera.setPreviewDisplay(surfaceView.getHolder()); camera.setDisplayOrientation(90); } catch (IOException e) { e.printStackTrace(); } backOrFtont = 1; camera.startPreview(); break; } else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK && backOrFtont == 1) { camera.stopPreview(); camera.release(); camera = null; camera = Camera.open(i); try { camera.setPreviewDisplay(surfaceView.getHolder()); camera.setDisplayOrientation(90); } catch (IOException e) { e.printStackTrace(); } camera.startPreview(); backOrFtont = 0; break; } } } public void stopRecord() { mediaRecorder.release(); camera.release(); mediaRecorder = null; camera = Camera.open(); mediaRecorder = new MediaRecorder(); doChange(surfaceView.getHolder()); } public void stop() { if (mediaRecorder != null && camera != null) { mediaRecorder.release(); camera.release(); } } public void destroy() { if (mediaRecorder != null && camera != null) { mediaRecorder.release(); camera.release(); mediaRecorder = null; camera = null; } } /** * @param path 保存的路径 * @param name 录像视频名称(不包含后缀) */ public void startRecord(String path, String name) { camera.unlock(); mediaRecorder.setCamera(camera); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); //mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW)); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediaRecorder.setVideoEncodingBitRate(700 * 1024); mediaRecorder.setVideoSize(width, height); mediaRecorder.setVideoFrameRate(24); //getVideoSize(); File file = new File(path); if (!file.exists()) { file.mkdirs(); } mediaRecorder.setOutputFile(path + File.separator + name + ".mp4"); File file1 = new File(path + File.separator + name + ".mp4"); if (file1.exists()) { file1.delete(); } mediaRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface()); /***不设置时,录制的视频总是倒着,翻屏导致视频上下翻滚*/ mediaRecorder.setOrientationHint(0); try { mediaRecorder.prepare(); mediaRecorder.start(); } catch (IOException e) { e.printStackTrace(); } } /*** * 获取SupportedVideoSizes 控制输出视频width在300到600之间(尽可能小) * 获取PictureSize的大小(控制在w:1000-2000之间) */ public void getVideoSize() { Camera.Parameters parameters = camera.getParameters(); List<Camera.Size> videoSize = parameters.getSupportedVideoSizes(); for (int i = 0; i < videoSize.size(); i++) { int width1 = videoSize.get(i).width; int height1 = videoSize.get(i).height; if (width1 >= 300 && width1 <= 600) { if (height1 >= 200 && height1 <= 600) { width = width1; height = height1; } } Log.d(TAG, "getVideoSize:----w:-- " + videoSize.get(i).width + "---h:--" + videoSize.get(i).height); } List<Camera.Size> photoSize = parameters.getSupportedPictureSizes(); for (int i = 0; i < photoSize.size(); i++) { int width1 = photoSize.get(i).width; int height1 = photoSize.get(i).height; if (width1 >= 1000 && width1 <= 2000) { if (height1 >= 600 && height1 <=2000) { widthPhoto = width1; heightPhoto = height1; } } } } public void takePicture(String photoPath, String photoName) { camera.takePicture(null, null, new PictureCallBack(photoPath, photoName)); } /** * 聚焦 */ public void focus(){ Camera.Parameters parameters=camera.getParameters(); parameters.setPictureSize(widthPhoto,heightPhoto); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); camera.setParameters(parameters); camera.cancelAutoFocus(); } /*** 拍照功能*/ private class PictureCallBack implements Camera.PictureCallback { /*** 照片保存的路径和名称*/ private String path; private String name; public PictureCallBack(String path, String name) { this.path = path; this.name = name; } @Override public void onPictureTaken(byte[] bytes, Camera camera) { File file1 = new File(path); if (!file1.exists()) { file1.mkdirs(); } File file = new File(path, name); if (file.exists()) { file.delete(); } FileOutputStream fos = null; try { fos = new FileOutputStream(file); try { fos.write(bytes); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } camera.startPreview(); } } }