Android自定义相机实现定时拍照

来源:互联网 发布:围棋打谱 mac 编辑:程序博客网 时间:2024/05/21 15:41

这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能。

首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件:

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <SurfaceView        android:id="@+id/surface_view"        android:layout_width="match_parent"        android:layout_height="match_parent" />    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical" >        <ImageView            android:id="@+id/start"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerHorizontal="true"            android:layout_alignParentBottom="true"            android:layout_marginBottom="10dp"            android:src="@drawable/capture"/>        <TextView            android:id="@+id/count_down"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:layout_gravity="center"            android:gravity="center"            android:textSize="80sp"/>    </RelativeLayout></FrameLayout>

MainActivity.java

package com.jackie.timercamera;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.hardware.Camera;import android.media.AudioManager;import android.media.MediaPlayer;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback,        View.OnClickListener, Camera.PictureCallback {    private SurfaceView mSurfaceView;    private ImageView mIvStart;    private TextView mTvCountDown;    private SurfaceHolder mHolder;    private Camera mCamera;    private Handler mHandler = new Handler();    private int mCurrentTimer = 10;    private boolean mIsSurfaceCreated = false;    private boolean mIsTimerRunning = false;    private static final int CAMERA_ID = 0; //后置摄像头//    private static final int CAMERA_ID = 1; //前置摄像头    private static final String TAG = MainActivity.class.getSimpleName();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initEvent();    }    @Override    protected void onPause() {        super.onPause();        stopPreview();    }    private void initView() {        mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);        mIvStart = (ImageView) findViewById(R.id.start);        mTvCountDown = (TextView) findViewById(R.id.count_down);    }    private void initEvent() {        mHolder = mSurfaceView.getHolder();        mHolder.addCallback(this);        mIvStart.setOnClickListener(this);    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        mIsSurfaceCreated = true;    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        startPreview();    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        mIsSurfaceCreated = false;    }    private void startPreview() {        if (mCamera != null || !mIsSurfaceCreated) {            Log.d(TAG, "startPreview will return");            return;        }        mCamera = Camera.open(CAMERA_ID);        Camera.Parameters parameters = mCamera.getParameters();        int width = getResources().getDisplayMetrics().widthPixels;        int height = getResources().getDisplayMetrics().heightPixels;        Camera.Size size = getBestPreviewSize(width, height, parameters);        if (size != null) {            //设置预览分辨率            parameters.setPreviewSize(size.width, size.height);            //设置保存图片的大小            parameters.setPictureSize(size.width, size.height);        }        //自动对焦        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);        parameters.setPreviewFrameRate(20);        //设置相机预览方向        mCamera.setDisplayOrientation(90);        mCamera.setParameters(parameters);        try {            mCamera.setPreviewDisplay(mHolder);        } catch (Exception e) {            Log.d(TAG, e.getMessage());        }        mCamera.startPreview();    }    private void stopPreview() {        //释放Camera对象        if (mCamera != null) {            try {                mCamera.setPreviewDisplay(null);                mCamera.stopPreview();                mCamera.release();                mCamera = null;            } catch (Exception e) {                Log.e(TAG, e.getMessage());            }        }    }    private Camera.Size getBestPreviewSize(int width, int height,                                           Camera.Parameters parameters) {        Camera.Size result = null;        for (Camera.Size size : parameters.getSupportedPreviewSizes()) {            if (size.width <= width && size.height <= height) {                if (result == null) {                    result = size;                } else {                    int resultArea = result.width * result.height;                    int newArea = size.width * size.height;                    if (newArea > resultArea) {                        result = size;                    }                }            }        }        return result;    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.start:                if (!mIsTimerRunning) {                    mIsTimerRunning = true;                    mHandler.post(timerRunnable);                }                break;        }    }    private Runnable timerRunnable = new Runnable() {        @Override        public void run() {            if (mCurrentTimer > 0) {                mTvCountDown.setText(mCurrentTimer + "");                mCurrentTimer--;                mHandler.postDelayed(timerRunnable, 1000);            } else {                mTvCountDown.setText("");                mCamera.takePicture(null, null, null, MainActivity.this);                playSound();                mIsTimerRunning = false;                mCurrentTimer = 10;            }        }    };    @Override    public void onPictureTaken(byte[] data, Camera camera) {        try {            FileOutputStream fos = new FileOutputStream(new File                    (Environment.getExternalStorageDirectory() + File.separator +                            System.currentTimeMillis() + ".png"));            //旋转角度,保证保存的图片方向是对的            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);            Matrix matrix = new Matrix();            matrix.setRotate(90);            bitmap = Bitmap.createBitmap(bitmap, 0, 0,                    bitmap.getWidth(), bitmap.getHeight(), matrix, true);            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);            fos.flush();            fos.close();        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        mCamera.startPreview();    }    /**     *   播放系统拍照声音     */    public void playSound() {        MediaPlayer mediaPlayer = null;        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);        int volume = audioManager.getStreamVolume( AudioManager.STREAM_NOTIFICATION);        if (volume != 0) {            if (mediaPlayer == null)                mediaPlayer = MediaPlayer.create(this,                         Uri.parse("file:///system/media/audio/ui/camera_click.ogg"));            if (mediaPlayer != null) {                mediaPlayer.start();            }        }    }}

有两点需要注意:对于Camera来说,默认是横屏的,所以预览的时候和图片保存的时候都是横屏的,需要调整角度。

设置相机预览方法:

//设置相机预览方向mCamera.setDisplayOrientation(90);
保存图片的时候调整角度:
效果图如下:


0 0