Android Camera+SurfaceView实现自定义拍照

jopen 9年前

          对Activity强制横屏,保证预览方向正确。使用OrientationEventListener监听设备方向,判断竖拍时,旋转照片后再保存,保证竖拍时预览图片和保存后的图片方向一致。

      运行效果:

 Android Camera+SurfaceView实现自定义拍照


代码:

TestCameraActivity.java
    package com.example.testcamera;                import java.io.ByteArrayOutputStream;        import java.io.FileOutputStream;        import java.io.IOException;        import java.util.List;        import java.util.UUID;                import android.annotation.SuppressLint;        import android.app.Activity;        import android.content.Context;        import android.content.Intent;        import android.graphics.Bitmap;        import android.graphics.BitmapFactory;        import android.graphics.Matrix;        import android.hardware.Camera;        import android.hardware.Camera.Parameters;        import android.hardware.Camera.Size;        import android.os.Build;        import android.os.Bundle;        import android.util.Log;        import android.view.OrientationEventListener;        import android.view.SurfaceHolder;        import android.view.SurfaceView;        import android.view.View;        import android.view.View.OnClickListener;        import android.widget.Button;                public class TestCameraActivity extends Activity implements OnClickListener,                SurfaceHolder.Callback {            private static final String TAG = "TestCameraActivity";            public static final String KEY_FILENAME = "filename";            private Button mTakePhoto;            private SurfaceView mSurfaceView;            private Camera mCamera;            private String mFileName;            private OrientationEventListener mOrEventListener; // 设备方向监听器            private Boolean mCurrentOrientation; // 当前设备方向 横屏false,竖屏true                    /* 图像数据处理还未完成时的回调函数 */            private Camera.ShutterCallback mShutter = new Camera.ShutterCallback() {                @Override                public void onShutter() {                    // 一般显示进度条                }            };                    /* 图像数据处理完成后的回调函数 */            private Camera.PictureCallback mJpeg = new Camera.PictureCallback() {                        @Override                public void onPictureTaken(byte[] data, Camera camera) {                    // 保存图片                    mFileName = UUID.randomUUID().toString() + ".jpg";                    Log.i(TAG, mFileName);                    FileOutputStream out = null;                    try {                        out = openFileOutput(mFileName, Context.MODE_PRIVATE);                        byte[] newData = null;                        if (mCurrentOrientation) {                            // 竖屏时,旋转图片再保存                            Bitmap oldBitmap = BitmapFactory.decodeByteArray(data, 0,                                    data.length);                            Matrix matrix = new Matrix();                            matrix.setRotate(90);                            Bitmap newBitmap = Bitmap.createBitmap(oldBitmap, 0, 0,                                    oldBitmap.getWidth(), oldBitmap.getHeight(),                                    matrix, true);                            ByteArrayOutputStream baos = new ByteArrayOutputStream();                            newBitmap.compress(Bitmap.CompressFormat.JPEG, 85, baos);                            newData = baos.toByteArray();                            out.write(newData);                        } else {                            out.write(data);                        }                            } catch (IOException e) {                        e.printStackTrace();                    } finally {                        try {                            if (out != null)                                out.close();                        } catch (IOException e) {                            e.printStackTrace();                        }                    }                    Intent i = new Intent(TestCameraActivity.this, ShowPicture.class);                    i.putExtra(KEY_FILENAME, mFileName);                    startActivity(i);                    finish();                }            };                    @SuppressWarnings("deprecation")            @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_test_camera);                mTakePhoto = (Button) findViewById(R.id.take_photo);                mTakePhoto.setOnClickListener(this); // 拍照按钮监听器                        startOrientationChangeListener(); // 启动设备方向监听器                mSurfaceView = (SurfaceView) findViewById(R.id.my_surfaceView);                SurfaceHolder holder = mSurfaceView.getHolder();                holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);                holder.addCallback(this); // 回调接口                    }                    private final void startOrientationChangeListener() {                mOrEventListener = new OrientationEventListener(this) {                    @Override                    public void onOrientationChanged(int rotation) {                        if (((rotation >= 0) && (rotation <= 45)) || (rotation >= 315)                                || ((rotation >= 135) && (rotation <= 225))) {// portrait                            mCurrentOrientation = true;                            Log.i(TAG, "竖屏");                        } else if (((rotation > 45) && (rotation < 135))                                || ((rotation > 225) && (rotation < 315))) {// landscape                            mCurrentOrientation = false;                            Log.i(TAG, "横屏");                        }                    }                };                mOrEventListener.enable();            }                    @Override            public void onClick(View v) {                // 点击拍照                switch (v.getId()) {                case R.id.take_photo:                    mCamera.takePicture(mShutter, null, mJpeg);                    break;                default:                    break;                }                    }                    @Override            public void surfaceChanged(SurfaceHolder holder, int format, int width,                    int height) {                // SurfaceView尺寸发生改变时(首次在屏幕上显示同样会调用此方法),初始化mCamera参数,启动Camera预览                        Parameters parameters = mCamera.getParameters();// 获取mCamera的参数对象                Size largestSize = getBestSupportedSize(parameters                        .getSupportedPreviewSizes());                parameters.setPreviewSize(largestSize.width, largestSize.height);// 设置预览图片尺寸                largestSize = getBestSupportedSize(parameters                        .getSupportedPictureSizes());// 设置捕捉图片尺寸                parameters.setPictureSize(largestSize.width, largestSize.height);                mCamera.setParameters(parameters);                        try {                    mCamera.startPreview();                } catch (Exception e) {                    if (mCamera != null) {                        mCamera.release();                        mCamera = null;                    }                }                    }                    @Override            public void surfaceCreated(SurfaceHolder holder) {                // SurfaceView创建时,建立Camera和SurfaceView的联系                if (mCamera != null) {                    try {                        mCamera.setPreviewDisplay(holder);                    } catch (IOException e) {                        e.printStackTrace();                    }                }                    }                    @Override            public void surfaceDestroyed(SurfaceHolder holder) {                // SurfaceView销毁时,取消Camera预览                if (mCamera != null) {                    mCamera.stopPreview();                }            }                    @SuppressLint("NewApi")            @Override            public void onResume() {                super.onResume();                // 开启相机                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {                    mCamera = Camera.open(0);                    // i=0 表示后置相机                } else                    mCamera = Camera.open();            }                    @Override            public void onPause() {                super.onPause();                // 释放相机                if (mCamera != null) {                    mCamera.release();                    mCamera = null;                }                    }                    private Size getBestSupportedSize(List<Size> sizes) {                // 取能适用的最大的SIZE                Size largestSize = sizes.get(0);                int largestArea = sizes.get(0).height * sizes.get(0).width;                for (Size s : sizes) {                    int area = s.width * s.height;                    if (area > largestArea) {                        largestArea = area;                        largestSize = s;                    }                }                return largestSize;            }        }  
ShowPicture.java
    package com.example.testcamera;                import android.app.Activity;        import android.graphics.Bitmap;        import android.graphics.BitmapFactory;        import android.graphics.drawable.BitmapDrawable;        import android.os.Bundle;        import android.util.Log;        import android.view.Display;        import android.widget.ImageView;                public class ShowPicture extends Activity {                    private static final String TAG = "ShowPicture";            private ImageView mPicture;                    public void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_show_picture);                        mPicture = (ImageView) findViewById(R.id.picture);                String fileName = getIntent().getStringExtra(                        TestCameraActivity.KEY_FILENAME);                // 图片路径                Log.i(TAG, fileName);                String path = getFileStreamPath(fileName).getAbsolutePath();                        Display display = getWindowManager().getDefaultDisplay(); // 显示屏尺寸                float destWidth = display.getWidth();                float destHeight = display.getHeight();                        // 读取本地图片尺寸                BitmapFactory.Options options = new BitmapFactory.Options();                options.inJustDecodeBounds = true;                BitmapFactory.decodeFile(path, options);// 设置为true,options依然对应此图片,但解码器不会为此图片分配内存                        float srcWidth = options.outWidth;                float srcHeight = options.outHeight;                        int inSampleSize = 1;                if (srcHeight > destHeight || srcWidth > destWidth) { // 当图片长宽大于屏幕长宽时                    if (srcWidth > srcHeight) {                        inSampleSize = Math.round(srcHeight / destHeight);                    } else {                        inSampleSize = Math.round(srcWidth / destWidth);                    }                }                options = new BitmapFactory.Options();                options.inSampleSize = inSampleSize;                        Bitmap bitmap = BitmapFactory.decodeFile(path, options);                BitmapDrawable bDrawable = new BitmapDrawable(getResources(), bitmap);                mPicture.setImageDrawable(bDrawable);            }                    @Override            public void onDestroy() {                if (!(mPicture.getDrawable() instanceof BitmapDrawable))                    return;                // 释放bitmap占用的空间                BitmapDrawable b = (BitmapDrawable) mPicture.getDrawable();                b.getBitmap().recycle();                mPicture.setImageDrawable(null);            }                }  
来自:http://blog.csdn.net/u012964281/article/details/41143169