android 7自定义相机预览及拍照功能

本文实例为大家分享了Android实现摄像头切换,拍照及保存到相册,预览等功能,解决android7拍照之后不能连续预览的问题、参数设置相关问题以及前后摄像头语言颠倒等问题。

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView; 

import com.hama.tracker.R; 

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; 

public class CamaraActivity extends Activity implements View.OnClickListener { 

 @Bind(R.id.return_back)
 TextView returnBack;
 @Bind(R.id.tvswitch_camera)
 TextView tvswitchCamera;
 //启动摄像机
 private Camera mCamera; 

 public boolean isopen_camara = false;
 private SurfaceView surfaceView;
 private SurfaceHolder mholder = null;
 private SurfaceCallback previewCallBack;
 private boolean isTakingPhoto;//是否正在拍照 

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  verifyPermission(new String[]{Manifest.permission.CAMERA});
  // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
  setContentView(R.layout.activity_camara);
  ButterKnife.bind(this); 

  // 预览控件
  surfaceView = (SurfaceView) this
    .findViewById(R.id.surfaceView);
  // 设置参数
  surfaceView.getHolder().setKeepScreenOn(true);
  surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

  returnBack.setOnClickListener(this);
  tvswitchCamera.setOnClickListener(this);
  EventBus.getDefault().register(this);
 } 

 public void verifyPermission(String[] permissions) {
  if (permissions != null) {
   List<String> lists = new ArrayList<>();
   for (int i = 0; i < permissions.length; i++) {
    if (ActivityCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
     if (ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) { 

     }
     lists.add(permissions[i]);
    }
   }
   if (lists.size() > 0) {
    String[] ps = new String[lists.size()];
    for (int i = 0; i < lists.size(); i++) {
     ps[i] = lists.get(i);
    }
    ActivityCompat.requestPermissions(this, ps, 1);
   }
  }
 } 

 @Override
 protected void onRestart() {
  super.onRestart();
 } 

 @Override
 protected void onStart() {
  super.onStart();
 } 

 private void takePhoto() {
  if (!isopen_camara) {
   previewCallBack = new SurfaceCallback();
   surfaceView.getHolder().addCallback(previewCallBack);
  } else {
   autoTakePhoto();
  }
 } 

 @Override
 protected void onResume() {
  super.onResume();
  if(mCamera == null){
   if (!isopen_camara) {
    previewCallBack = new SurfaceCallback();
    surfaceView.getHolder().addCallback(previewCallBack);
   }
  } 

 } 

 @Override
 public void onClick(View v) {
  switch (v.getId()) {
   case R.id.return_back:
    finish();
    break;
   case R.id.tvswitch_camera:
    switchCamara();
    break;
  }
 } 

 // 预览界面回调
 private final class SurfaceCallback implements SurfaceHolder.Callback {
  // 预览界面被创建
  public void surfaceCreated(SurfaceHolder holder) {
   try {
    //1代表打开后置摄像头,0代表打开前置摄像头.
    mCamera = Camera.open(cameraPosition);// 打开摄像头
    setParams(holder,cameraPosition);
   } catch (Exception e) {
    e.printStackTrace();
    if (mCamera != null) {
     mCamera.stopPreview();
     mCamera.lock();
     mCamera.release();
     mCamera = null;
    }
    finish();
    //Toast.makeText(getApplicationContext(), "该手机不支持自动拍照功能", Toast.LENGTH_LONG).show();
   }
  } 

  public void surfaceChanged(SurfaceHolder holder, int format, int width,
         int height) {
   System.out.println("surfaceChanged");
   isopen_camara = true;
   //autoTakePhoto();
  } 

  // 预览界面被销毁
  public void surfaceDestroyed(SurfaceHolder holder) {
   System.out.println("surfaceDestroyed");
   if(!isopen_camara)
    return;
   if (mCamera != null) {
    holder.removeCallback(this);
    mCamera.setPreviewCallback(null);
    mCamera.stopPreview();
    mCamera.lock();
    mCamera.release();
    mCamera = null;
   }
  } 

 } 

 public void reset(){
  Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
  if (mCamera != null) {
   if(surfaceView != null && surfaceView.getHolder() != null && previewCallBack != null){
    surfaceView.getHolder().removeCallback(previewCallBack);
   }
   mCamera.setPreviewCallback(null);
   mCamera.stopPreview();
   mCamera.lock();
   mCamera.release();
   mCamera = null; 

   mCamera = Camera.open(cameraPosition);
   if (null != mholder)
    setParams(mholder,cameraInfo.facing);
  } 

 } 

 @Override
 protected void onDestroy() {
  super.onDestroy();
  if (mCamera != null) {
   if(surfaceView != null && surfaceView.getHolder() != null && previewCallBack != null){
    surfaceView.getHolder().removeCallback(previewCallBack);
   }
   mCamera.setPreviewCallback(null);
   mCamera.stopPreview();
   mCamera.lock();
   mCamera.release();
   mCamera = null;
  }
  ButterKnife.unbind(this);
  EventBus.getDefault().unregister(this);
 } 

 private void setParams(SurfaceHolder mySurfaceView,int postion) {
  try {
   int PreviewWidth = 0;
   int PreviewHeight = 0;
   WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);//获取窗口的管理器
   /*PreviewWidth = display.();
   PreviewHeight = display.getHeight();*/ 

   Camera.Parameters parameters = mCamera.getParameters();
   // 选择合适的预览尺寸
   List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes(); 

   // 如果sizeList只有一个我们也没有必要做什么了,因为就他一个别无选择
   if (sizeList.size() > 1) {
    Iterator<Camera.Size> itor = sizeList.iterator();
    while (itor.hasNext()) {
     Camera.Size cur = itor.next();
     /*if (cur.width >= PreviewWidth
       && cur.height >= PreviewHeight) {*/
     if (cur.width >= PreviewWidth
       && cur.height >= PreviewHeight) {
      PreviewWidth = cur.width;
      PreviewHeight = cur.height;
      break;
     } 

    }
   }
   parameters.setPreviewSize(PreviewWidth, PreviewHeight); //获得摄像区域的大小
   //parameters.setPreviewFrameRate(3);//每秒3帧 每秒从摄像头里面获得3个画面
   //parameters.setPreviewFpsRange(3,);
   List<int[]> list = parameters.getSupportedPreviewFpsRange();
   int[] v = null;
   int index = 0;
   int min = 0;
   for (int i = 0; i < list.size(); i++) {
    v = list.get(i);
    if (v[0] > min) {
     min = v[0];
     index = i;
    }
   }
   parameters.setPreviewFpsRange(list.get(index)[0], list.get(index)[1]);
   parameters.setPictureFormat(PixelFormat.JPEG);//设置照片输出的格式
   parameters.set("jpeg-quality", 85);//设置照片质量
   parameters.setPictureSize(PreviewWidth, PreviewHeight);//设置拍出来的屏幕大小
   parameters.setRotation(180); //Java部分
   if (Build.VERSION.SDK_INT >= 24) {
    if(postion == 0){
     mCamera.setDisplayOrientation(90);
    }else {
     mCamera.setDisplayOrientation(270);
    }
   } else {
    mCamera.setDisplayOrientation(90);
   } 

   mCamera.setParameters(parameters);//把上面的设置 赋给摄像头
   mCamera.setPreviewDisplay(mySurfaceView);//把摄像头获得画面显示在SurfaceView控件里面
   mholder = mySurfaceView;
   mCamera.setPreviewCallback(new Camera.PreviewCallback() {
    @Override
    public void onPreviewFrame(byte[] data, Camera camera) { 

    }
   });
   mCamera.startPreview();//开始预览
   // mPreviewRunning = true;
  } catch (IOException e) {
   Log.e("tag", e.toString());
  }
 } 

 Handler handler = null; 

 private void autoTakePhoto() {
  // 拍照前需要对焦 获取清析的图片
  if (null == mCamera) return;
  mCamera.autoFocus(new Camera.AutoFocusCallback() {
   @Override
   public void onAutoFocus(boolean success, Camera camera) { 

    if (success && isopen_camara) {
     // 对焦成功
     // Toast.makeText(MainActivity.this, "对焦成功 !!",Toast.LENGTH_SHORT).show();
     if(!isTakingPhoto) {
      isTakingPhoto = true;
      handler = new Handler();
      handler.post(new Runnable() {
       @Override
       public void run() {
        mCamera.takePicture(null, null, new MyPictureCallback());
       }
      });
     }
    }
   }
  });
 } 

 // 照片回调
 private final class MyPictureCallback implements Camera.PictureCallback {
  // 照片生成后
  @Override
  public void onPictureTaken(byte[] data, Camera camera) {
   try {
    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
    Matrix matrix = new Matrix();
    matrix.setRotate(270); 

    File jpgFile = new File(Environment.getExternalStorageDirectory() + "/DCIM/camera");
    if (!jpgFile.exists()) {
     jpgFile.mkdir();
    }
    File jpgFile1 = new File(jpgFile.getAbsoluteFile(), System.currentTimeMillis() + ".jpg");
    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    FileOutputStream fos = new FileOutputStream(jpgFile1);
    bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos);
    ToastUtils.show(getApplicationContext(), getString(R.string.save_success));
    fos.close();
    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    Uri uri = Uri.fromFile(jpgFile1);
    intent.setData(uri);
    sendBroadcast(intent);
   } catch (Exception e) {
    e.printStackTrace();
   }finally {
    if(Build.VERSION.SDK_INT>=24){
     reset();
    }
    isTakingPhoto = false;
   }
  }
 } 

 private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头 

 private void switchCamara() {
  //切换前后摄像头
  int cameraCount = 0;
  Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
  cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数 

  for (int i = 0; i < cameraCount; i++) {
   Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
   if (cameraPosition == 1) {
    //现在是后置,变更为前置
    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置  CAMERA_FACING_BACK后置
     if(surfaceView != null && surfaceView.getHolder() != null && previewCallBack != null){
      surfaceView.getHolder().removeCallback(previewCallBack);
     }
     mCamera.setPreviewCallback(null);
     mCamera.stopPreview();//停掉原来摄像头的预览
     mCamera.lock();
     mCamera.release();//释放资源
     mCamera = null;//取消原来摄像头
     mCamera = Camera.open(i);//打开当前选中的摄像头
     /* try {
      if (null != mholder)
       mCamera.setPreviewDisplay(mholder);//通过surfaceview显示取景画面
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
     mCamera.startPreview();//开始预览*/
     if (null != mholder)
      setParams(mholder,Camera.CameraInfo.CAMERA_FACING_BACK);
     cameraPosition = 0;
     break;
    }
   } else {
    //现在是前置, 变更为后置
    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置  CAMERA_FACING_BACK后置
     if(surfaceView != null && surfaceView.getHolder() != null && previewCallBack != null){
      surfaceView.getHolder().removeCallback(previewCallBack);
     }
     mCamera.setPreviewCallback(null);
     mCamera.stopPreview();//停掉原来摄像头的预览
     mCamera.lock();
     mCamera.release();//释放资源
     mCamera = null;//取消原来摄像头
     mCamera = Camera.open(i);//打开当前选中的摄像头
     /*try {
      if (null != mholder)
       mCamera.setPreviewDisplay(mholder);//通过surfaceview显示取景画面
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
     mCamera.startPreview();//开始预览*/
     if (null != mholder)
      setParams(mholder,Camera.CameraInfo.CAMERA_FACING_FRONT);
     cameraPosition = 1;
     break;
    }
   } 

  }
 } 

 @Override
 public boolean onKeyDown(int keyCode, KeyEvent event) {
  if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {///音量减拍照
   takePhoto();
   return true;
  }
  return super.onKeyDown(keyCode, event); 

 }
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义照相机倒计时拍照

    自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: 两个TextView是用来显示提示信息和倒计时的秒数的 相关教程:Android开发从相机或相册获取图片裁剪 Android启动相机拍照并返回图片 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools&qu

  • Android打开系统相机并拍照的2种显示方法

    本文实例为大家分享了Android打开系统相机并拍照的具体实现代码,供大家参考,具体内容如下 目标效果: 第二张为点击第一个按钮拍照后显示的,比较模糊,第三章为点击第二个按钮拍照后显示的,比较清楚. 1.activity_main.xml页面设置布局. activity_main.xml页面: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="h

  • Android如何调用系统相机拍照

    本文实例为大家分享了Android调用系统相机拍照的具体代码,供大家参考,具体内容如下 /** * 调用系统相机 */ private void takePhoto() { Uri uri = null; if (which_image == FRONT_IMAGE) { frontFile = new File(getSDPath() +"/test/front_" + getDate() + ".jpg"); uri = Uri.fromFile(frontFi

  • Android调用系统照相机拍照与摄像的方法

    前言 在很多场景中,都需要用到摄像头去拍摄照片或视频,在照片或视频的基础之上进行处理.但是Android系统源码是开源的,很多设备厂商均可使用,并且定制比较混乱.一般而言,在需要用到摄像头拍照或摄像的时候,均会直接调用系统现有的相机应用,去进行拍照或摄像,我们只取它拍摄的结果进行处理,这样避免了不同设备的摄像头的一些细节问题.本篇博客将介绍在Android应用中,如何调用系统现有的相机应用去拍摄照片与短片,并对其进行处理,最后均会以一个简单的Demo来演示效果. 1.系统现有相机应用的调用 对于

  • Android 系统相机拍照后相片无法在相册中显示解决办法

    Android 系统相机拍照后相片无法在相册中显示解决办法 目前自己使用发送广播实现了效果 public void photo() { Intent openCameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(openCameraIntent, TAKE_PICTURE); } 解决方法: protected void onActivityResul

  • Android 实现调用系统照相机拍照和录像的功能

    本文实现android系统照相机的调用来拍照 项目的布局相当简单,只有一个Button: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_heig

  • Android实现从本地图库/相机拍照后裁剪图片并设置头像

    玩qq或者是微信的盆友都知道,这些聊天工具里都要设置头像,一般情况下大家的解决办法是从本地图库选择图片或是从相机拍照,然后根据自己的喜爱截取图片.上述过程已经实现好了,最后一步我加上了把截取好的图片在保存到本地的操作,来保存头像.为了大家需要,下面我们小编把完整的代码贴出来供大家参考. 先给大家展示效果图: 代码部分: 布局代码(其实就是两个按钮和一个ImageView来显示头像) <LinearLayout xmlns:android="http://schemas.android.co

  • Android编程实现调用相册、相机及拍照后直接裁剪的方法

    本文实例讲述了Android编程实现调用相册.相机及拍照后直接裁剪的方法.分享给大家供大家参考,具体如下: package com.cvte.health.phone; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import android.app.Activity; import android.content.ContentResolver; import android.co

  • Android启动相机拍照并返回图片

    具体实现过程请看下面代码: 简单的调用了一下系统的拍照功能 代码如下所示: //拍照的方法 private void openTakePhoto(){ /** * 在启动拍照之前最好先判断一下sdcard是否可用 */ String state = Environment.getExternalStorageState(); //拿到sdcard是否可用的状态码 if (state.equals(Environment.MEDIA_MOUNTED)){ //如果可用 Intent intent

  • Android 调用系统照相机拍照和录像

    本文实现android系统照相机的调用来拍照 项目的布局相当简单,只有一个Button: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_heig

  • Android使用系统自带的相机实现一键拍照功能

    今天分享的是用系统自带的相机实现一键拍照功能. public class MainActivity extends AppCompatActivity { private static final int TAKE_PHOTO = 100; private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setConte

  • Android自定义相机实现定时拍照功能

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="m

  • Android自定义组件获取本地图片和相机拍照图片

    iOS中有封装好的选择图片后长按出现动画删除效果,效果如下 而Android找了很久都没有找到有这样效果的第三方组件,最后懒得找了还是自己实现这效果吧 选择图片后还可对图片进行剪裁 当然,代码中还有很多不完善的地方,我接下来会继续完善这个组件的 已经上传到开源社区,欢迎大家来Star啊~ Demo源码:传送门 设计中的碰到的一些问题和解决思路 1.如何让加号图片显示在GridView最后面 首先在调用GridAdapter构造方法时就加载加号图片 /** * 图片适配器 * @param con

随机推荐