Android 开发之对拍照和录像功能的封装

版权声明:本文为博主原创文章,未经博主允许不得转载。欢迎访问http://github.com/shenhuanet 转载请注明出处: https://blog.csdn.net/klxh2009/article/details/68062195

Android 开发之对拍照和录像功能的封装

转载请注明出处 传送门 本文出自【付小华的博客】

介绍:

关于Android 自定义相机和自定义录像功能的封装有很多,我这里也封装了一个,与其它的不同,我这里是非常简便和轻量级的封装,只有一个类(继承自TextureView),大家使用时只需要复制这个类就可以了。

使用:
  • 权限声明
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • 布局引用
<xxxxxxx.TextureCameraPreview
        android:id="@+id/texture_camera_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
  1. 拍照
    只需要在布局中引用即可直接打开相机预览。
    /**
     * 拍照
     *
     * @param listener 拍照监听,不可空
     */
    public void takePicture(OnPictureTakenListener listener)
// 声明变量
TextureCameraPreview mTextureCameraPreview;

// 拍照
mTextureCameraPreview.takePicture(new TextureCameraPreview.OnPictureTakenListener() {
    @Override
    public void onSuccess(byte[] data) {
        //TODO 拍照成功时回调
    }

    @Override
    public void onFailed(String msg) {
        //TODO 拍照失败时回调
    }
});
  1. 录像
    只需要在布局中引用即可直接打开相机预览。
    /**
     * 开始录像
     *
     * @param outputPath 输出录像保存文件路径,如"test.mp4"
     * @param listener   录像开始结束的监听,可空
     */
    public void startRecord(String outputPath, OnStartVideoListener listener)
// 声明变量
TextureCameraPreview mTextureCameraPreview;

// 录像
// 判断是否正处于录像
if (!mTextureCameraPreview.isRecording()) {
            mTextureCameraPreview.startRecord("test.mp4", new TextureCameraPreview.OnStartVideoListener() {
        @Override
        public void onStart() {
            // TODO: 开始录像时的回调
        }

        @Override
        public void onStop() {
            // TODO: 录像结束时的回调
        }
    });
}

// 需要在onPause中结束录像
@Override
public void onPause() {
    super.onPause();
    if (mTextureCameraPreview.isRecording()) {
        // 结束录像
        mTextureCameraPreview.stopRecord();
    }
}
  • 其它方法
    /**
     * 预览界面放大
     *
     * @param progress 放大倍数 0-100
     */
    public void setZoom(int progress)
    /**
     * 切换前后置摄像头
     *
     * @param index 0为后置摄像头,1为前置摄像头
     */
    public void switchCamera(int index)
代码:
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.media.ToneGenerator;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.TextureView;
import android.widget.Toast;

/**
 * Created by shenhua on 3/29/2017.
 * Email [email protected]
 */
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.打开相机
        mCamera = getCameraInstance(getContext(), index);
        if (mCamera != null) {
            // 2.设置相机参数
            Camera.Parameters parameters = mCamera.getParameters();
            // 3.调整预览方向
            mCamera.setDisplayOrientation(90);
            // 4.设置预览尺寸
            parameters.setPreviewSize(1920, 1080);
            parameters.setPictureSize(1920, 1080);
            // 5.调整拍照图片方向
            if (index == 0)
                parameters.setRotation(90);
            if (index == 1)
                parameters.setRotation(270);
            mCamera.setParameters(parameters);
            // 6.开始相机预览
            try {
                mCamera.setPreviewTexture(mSurface);
                mCamera.startPreview();
            } 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) {
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        releaseCamera();
        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(i);
        } catch (Exception e) {
            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();
    }

}

至此,正文结束,如大家遇到问题,欢迎评论、私信或邮件。

猜你喜欢

转载自blog.csdn.net/klxh2009/article/details/68062195