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

运行效果:



代码:

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() {@Overridepublic void onShutter() {// 一般显示进度条}};/* 图像数据处理完成后的回调函数 */private Camera.PictureCallback mJpeg = new Camera.PictureCallback() {@Overridepublic 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")@Overrideprotected 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) {@Overridepublic void onOrientationChanged(int rotation) {if (((rotation >= 0) && (rotation <= 45)) || (rotation >= 315)|| ((rotation >= 135) && (rotation <= 225))) {// portraitmCurrentOrientation = true;Log.i(TAG, "竖屏");} else if (((rotation > 45) && (rotation < 135))|| ((rotation > 225) && (rotation < 315))) {// landscapemCurrentOrientation = false;Log.i(TAG, "横屏");}}};mOrEventListener.enable();}@Overridepublic void onClick(View v) {// 点击拍照switch (v.getId()) {case R.id.take_photo:mCamera.takePicture(mShutter, null, mJpeg);break;default:break;}}@Overridepublic 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;}}}@Overridepublic void surfaceCreated(SurfaceHolder holder) {// SurfaceView创建时,建立Camera和SurfaceView的联系if (mCamera != null) {try {mCamera.setPreviewDisplay(holder);} catch (IOException e) {e.printStackTrace();}}}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {// SurfaceView销毁时,取消Camera预览if (mCamera != null) {mCamera.stopPreview();}}@SuppressLint("NewApi")@Overridepublic void onResume() {super.onResume();// 开启相机if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {mCamera = Camera.open(0);// i=0 表示后置相机} elsemCamera = Camera.open();}@Overridepublic void onPause() {super.onPause();// 释放相机if (mCamera != null) {mCamera.release();mCamera = null;}}private Size getBestSupportedSize(List<Size> sizes) {// 取能适用的最大的SIZESize 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);}@Overridepublic void onDestroy() {if (!(mPicture.getDrawable() instanceof BitmapDrawable))return;// 释放bitmap占用的空间BitmapDrawable b = (BitmapDrawable) mPicture.getDrawable();b.getBitmap().recycle();mPicture.setImageDrawable(null);}}


源码下载

github:https://github.com/mandmLeee/CustomCameraDemo


更多相关文章

  1. android 拍照以及压缩处理
  2. Android(安卓)使用RoundedImageView得不到圆形图片,变成椭圆形的
  3. Android:使用TextureView预览Camera
  4. 图片内存溢出处理
  5. android检测设备方向
  6. android 给图片加文字、图片水印
  7. Android(安卓)APP原型图设计规范
  8. Android(安卓)ImageView 图片设置为透明
  9. Android实现一款不错Banner界面广告图片循环轮播

随机推荐

  1. 实例演绎php遍历数组与js遍历数组的区别
  2. <JVM下篇:性能监控与调优篇>05-分析GC日志
  3. <JVM中篇:字节码与类的加载篇>02-字节码指令
  4. PHP编程0804作业
  5. <JVM上篇:内存与垃圾回收篇>01-JVM与Java
  6. 0802 PHP编程作业
  7. 初识 vue 以及几个常用的 v-指令的介绍
  8. <JVM中篇:字节码与类的加载篇>03-类的加载过
  9. 初次学习前端必备的开发工具VS Code简单
  10. 「数据库架构」三分钟搞懂事务隔离级别和