1.添加权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
录像要用到的权限,动态申请一下
2.WindowManager添加一个窗口
private WindowManager mWindowManager;
private WindowManager.LayoutParams mLayoutParams;
private View mView;
private void initFloatWindow() {
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mLayoutParams = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
mLayoutParams.format = PixelFormat.RGBA_8888;
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
//窗口大小
mLayoutParams.width = 400;
mLayoutParams.height = 500;
//窗口出现位置
mLayoutParams.x = 0;
mLayoutParams.y = 0;
LayoutInflater layoutInflater = LayoutInflater.from(this);
//布局文件中需要一个SurfaceView
mView = layoutInflater.inflate(R.layout.float_recorder_window, null);
mView.setOnTouchListener(new FloatingOnTouchListener());//触摸移动窗口
mWindowManager.addView(mView, mLayoutParams);//添加悬浮窗口
prepareCamera2();
}
private class FloatingOnTouchListener implements View.OnTouchListener {
private int x;
private int y;
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = (int) event.getRawX();
y = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int nowX = (int) event.getRawX();
int nowY = (int) event.getRawY();
int movedX = nowX - x;
int movedY = nowY - y;
x = nowX;
y = nowY;
mLayoutParams.x = mLayoutParams.x + movedX;
mLayoutParams.y = mLayoutParams.y + movedY;
mWindowManager.updateViewLayout(view, mLayoutParams);
break;
default:
break;
}
return true;
}
}
3.初始化SurfaceView
private CameraManager mCameraManager;
private CameraCharacteristics mCameraCharacteristics;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Handler childHandler, mainHandler;
private String mCameraID;//摄像头 0 为后 1 为前
private ImageReader mImageReader;
private CameraCaptureSession mCameraCaptureSession;
private CameraDevice mCameraDevice;
private MediaRecorder mMediaRecorder;
private void prepareCamera2() {
mSurfaceView = mView.findViewById(R.id.recorder_window);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setKeepScreenOn(true);
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
openCamera2();
}
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width,
int height) {
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
if (null != mCameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
}
}
});
}
4.打开摄像头
@SuppressLint("MissingPermission")
private void openCamera2() {
mMediaRecorder = new MediaRecorder();
HandlerThread handlerThread = new HandlerThread("Camera2");
handlerThread.start();
childHandler = new Handler(handlerThread.getLooper());
mainHandler = new Handler(Looper.getMainLooper());
//拍照回调
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mImageReader = ImageReader.newInstance(400, 500, ImageFormat.JPEG, 1);
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
//处理照片
//
image.close();
}
}, mainHandler);
}
//打开摄像头
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
CameraDevice.StateCallback deviceCallBack = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
Log.i(TAG, "onOpened: ");
mCameraDevice = camera;
startRecorder();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
}
};
mCameraManager.openCamera("0", deviceCallBack, mainHandler);
}
} catch (Exception e) {
e.printStackTrace();
}
}
这里的两个Handler我也没搞懂干嘛用的,好兄弟可以研究下
5.开始录像
private void startRecorder() {
File path = new File(Environment.getExternalStorageDirectory());//视频存储位置
if (!path.exists()) {
path.mkdir();
}
String fileName = "test.mp4"; //文件名
File video = new File(path, fileName);
//配置录像
mMediaRecorder.reset();
CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//使用麦克风
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);//使用摄像头获取对象
mMediaRecorder.setOutputFormat(mProfile.fileFormat);
mMediaRecorder.setAudioEncoder(mProfile.audioCodec);
mMediaRecorder.setVideoEncoder(mProfile.videoCodec);
mMediaRecorder.setOutputFile(video.getAbsolutePath());
mMediaRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate);
mMediaRecorder.setAudioEncodingBitRate(mProfile.audioBitRate);
mMediaRecorder.setAudioChannels(mProfile.audioChannels);
mMediaRecorder.setAudioSamplingRate(mProfile.audioSampleRate);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.setOrientationHint(90);
try {
mMediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
//打开预览
try {
final CaptureRequest.Builder previewBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
//第一Target不添加视频无法播放,第二Target不添加无法预览
previewBuilder.addTarget(mMediaRecorder.getSurface());
previewBuilder.addTarget(mSurfaceHolder.getSurface());
mCameraDevice.createCaptureSession(Arrays.asList(mMediaRecorder.getSurface(),
mSurfaceHolder.getSurface(), mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
mCameraCaptureSession = session;
CaptureRequest previewRequest = previewBuilder.build();
try {
mCameraCaptureSession.setRepeatingRequest(previewRequest, null,
childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
}
}, childHandler);
mMediaRecorder.start();
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
6.拍照方法
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
public void takePhoto() {
if (mCameraDevice == null) return;
final CaptureRequest.Builder captureBuilder;
try {
captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(mImageReader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
//获取手机方向
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
mCameraCaptureSession.capture(captureBuilder.build(), null, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
7.结束录制
private void stopRecorder() {
if (mView!=null)
mWindowManager.removeView(mView);
if (mMediaRecorder != null) {
mMediaRecorder.setOnErrorListener(null);
mMediaRecorder.setOnInfoListener(null);
mMediaRecorder.setPreviewDisplay(null);
}
try {
mMediaRecorder.stop();
} catch (Exception e) {
e.printStackTrace();
}
mMediaRecorder.release();
}
查了好久才做出来? 太麻烦了T T
|