直接给代码吧,首先是MainActivity:
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import android.Manifest;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;import java.io.File;
import java.util.Timer;
import java.util.TimerTask;public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
private TextView btn_stop;
private Button btn;
private int recLen = 11;
private Boolean isRecording = false;
private SurfaceHolder mSurfaceHolder;
private MediaRecorder mediaRecorder;
private Camera mCamera;
private String mVecordFilepath;
Timer timer = new Timer();final Handler handler = new Handler(){@Overridepublic void handleMessage(Message msg){switch (msg.what){case 1:btn_stop.setText(""+recLen);if(recLen<0){timer.cancel();btn_stop.setVisibility(View.GONE);}}}
};
TimerTask task = new TimerTask() {@Overridepublic void run() {recLen--;Message message = new Message();message.what = 1;handler.sendMessage(message);//当倒计时时间到1的时候关闭录像if (recLen == 1){stopRecord();stopCamera();}}
};@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);btn_stop = findViewById(R.id.luxiangtimer);btn = findViewById(R.id.luxiangbtn);SurfaceView mSurfaceview = (SurfaceView) findViewById(R.id.surfaceview_luxiang);mSurfaceHolder = mSurfaceview.getHolder();checkPermission(this);initCamera();
}public void luxiang(View view){if (Build.VERSION.SDK_INT >= 23) {int REQUEST_CODE_CONTACT = 101;}btn_stop.setVisibility(View.VISIBLE);//这是是判断视频文件有没有创建,如果没有就返回boolean creakOk = createRecordDir();if (!creakOk) {return;}try {mCamera.unlock();setConfigRecord();mediaRecorder.prepare();mediaRecorder.start();} catch (Exception e) {Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG).show();}isRecording = true;timer.schedule(task,1000,1000);
}private void setConfigRecord() {mediaRecorder = new MediaRecorder();mediaRecorder.reset();mediaRecorder.setCamera(mCamera);mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {@Overridepublic void onError(MediaRecorder mr, int what, int extra) {}});//录像角度mediaRecorder.setOrientationHint(90);//使用SurfaceView预览mediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());//1.设置采集声音mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置采集图像mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//2.设置视频,音频的输出格式 mp4mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);//3.设置音频的编码格式mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);//设置图像的编码格式mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);mediaRecorder.setAudioEncodingBitRate(44100);if (mProfile.videoBitRate > 2 * 1024 * 1024) {mediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024);} else {mediaRecorder.setVideoEncodingBitRate(1024 * 1024);}mediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);mediaRecorder.setVideoSize(1280, 720);mediaRecorder.setOutputFile(mVecordFilepath);
}private void initCamera() {mCamera = Camera.open(0); //①mCamera.setDisplayOrientation(90);try {mCamera.setPreviewDisplay(mSurfaceHolder);mCamera.cancelAutoFocus();//此句加上 可自动聚焦 必须加Camera.Parameters parameters = mCamera.getParameters();//查询摄像头支持的分辨率parameters.getSupportedPreviewSizes();for (int i = 0; i < parameters.getSupportedPreviewSizes().size(); i++) {Log.i("<><><><>Width", parameters.getSupportedPreviewSizes().get(i).width + "");Log.i("<><><><>Height", parameters.getSupportedPreviewSizes().get(i).height + "");}//设置分辨率parameters.setPreviewSize(1280, 720);//设置聚焦模式parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);//缩短Recording启动时间parameters.setRecordingHint(true);//是否支持影像稳定能力,支持则开启if (parameters.isVideoStabilizationSupported())parameters.setVideoStabilization(true);mCamera.setParameters(parameters);mCamera.startPreview();} catch (Exception e) {}
}private boolean createRecordDir() {if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {Toast.makeText(this, "SD卡不存在!", Toast.LENGTH_SHORT).show();return false;}mVecordFilepath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/videotest/luxiangtest.mp4";File f = new File(mVecordFilepath);if(!f.exists()){try {f.createNewFile();}catch (Exception e){}}return true;
}private void stopRecord() {try {if (isRecording && mediaRecorder != null) {mediaRecorder.setOnErrorListener(null);mediaRecorder.setPreviewDisplay(null);mediaRecorder.stop();mediaRecorder.reset();mediaRecorder.release();mediaRecorder = null;isRecording = false;}}catch (Exception ex){//Toast.makeText(getApplicationContext(),ex.getMessage(),1).show();}
}private void stopCamera() {if (mCamera != null) {mCamera.setPreviewCallback(null);mCamera.stopPreview();mCamera.release();mCamera = null;}
}public static void checkPermission(AppCompatActivity activity) {if (Build.VERSION.SDK_INT >= 23) {int checkPermission =ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO)+ ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_STATE)+ ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)+ ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);if (checkPermission != PackageManager.PERMISSION_GRANTED) {//动态申请ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.READ_PHONE_STATE,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);return;} else {return;}}return;
}@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {Log.d("111","surfaceCreated");
}@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {Log.d("111","surfaceChanged");
}@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {Log.d("111","surfaceDestroyed");
}
}
下面是布局文件:
<?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=".MainActivity"><SurfaceViewandroid:id="@+id/surfaceview_luxiang"android:layout_width="match_parent"android:layout_height="400dp" /><TextViewandroid:id="@+id/luxiangtimer"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"android:layout_below="@id/surfaceview_luxiang"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/luxiangbtn"android:layout_below="@id/luxiangtimer"android:text="录像"android:onClick="luxiang"tools:ignore="OnClick" /></RelativeLayout>
下面是版本号:
下面是权限,我这里权限比较多,不光是录像的,不需要的可以删掉:
这样就可以运行啦~