android自定义Camera实现录像和拍照

本文实例为大家分享了android自定义Camera实现录像和拍照的具体代码,供大家参考,具体内容如下

源码:

package com.example.myvideocamera;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**
 * 视频录制
 */
@SuppressWarnings("deprecation")
public class MainActivity extends Activity implements OnClickListener,
 SensorEventListener, Callback {
 private SurfaceView surfaceView; // 用于绘制缓冲图像的
 private Button luXiang_bt; // 开始录制的按钮
 private Button tingZhi_bt; // 停止录制的按钮
 private Button auto_focus; // 进行对焦
 private Button screenshot; // 截图
 private TextView time_tv; // 显示时间的文本框
 private MediaRecorder mRecorder;
 private boolean recording; // 记录是否正在录像,fasle为未录像, true 为正在录像
 private File videoFolder; // 存放视频的文件夹
 private File videFile; // 视频文件
 private Handler handler;
 private int time; // 时间
 private Camera myCamera; // 相机声明
 private SurfaceHolder holder; // 用来访问surfaceview的接口
 private SensorManager sManager; // 传感器管理者
 private Sensor sensor; // 传感器对象
 private int mX, mY, mZ; // x y z 坐标
 private Calendar calendar; // 日历
 private long lasttimestamp = 0; // 上一次用时的标志

 /**
 * 录制过程中,时间变化
 */
 private Runnable timeRun = new Runnable() {

 @Override
 public void run() {
  time++;
  time_tv.setText(time + "秒");
  handler.postDelayed(timeRun, 1000);
 }
 };

 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);// 强制横屏
 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  WindowManager.LayoutParams.FLAG_FULLSCREEN);
 setContentView(R.layout.activity_main);
 initView();
 initSensor();
 initCreateFile();
 }

 /**
 * 对传感器进行初始化
 */
 private void initSensor() {
 sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
 sensor = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
 if (sManager == null) {
  // throw new IllegalArgumentException("SensorManager is null");
 }
 sManager.registerListener(this, sensor,
  SensorManager.SENSOR_DELAY_NORMAL);
 }

 /**
 * 文件的创建
 */
 private void initCreateFile() {
 // 判断sd卡是否存在
 boolean sdCardExist = Environment.getExternalStorageState().equals(
  android.os.Environment.MEDIA_MOUNTED);
 if (sdCardExist) {
  // 设定存放视频的文件夹的路径
  String path = Environment.getExternalStorageDirectory()
   .getAbsolutePath()
   + File.separator
   + "VideoFolder"
   + File.separator;
  // 声明存放视频的文件夹的File对象
  videoFolder = new File(path);
  // 如果不存在此文件夹,则创建
  if (!videoFolder.exists()) {
  videoFolder.mkdirs();
  }
  // 设置surfaceView不管理的缓冲区
  surfaceView.getHolder().setType(
   SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  // 设置surfaceView分辨率
  //surfaceView.getHolder().setFixedSize(1000, 500);
  luXiang_bt.setOnClickListener(this);
 } else
  Toast.makeText(this, "未找到sdCard!", Toast.LENGTH_LONG).show();
 }

 /**
 * 初始化工作
 */
 private void initView() {
 // 获取控件
 surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
 luXiang_bt = (Button) findViewById(R.id.luXiang_bt);
 tingZhi_bt = (Button) findViewById(R.id.tingZhi_bt);
 time_tv = (TextView) findViewById(R.id.time);
 auto_focus = (Button) findViewById(R.id.auto_focus);
 screenshot = (Button) findViewById(R.id.screenshot);
 handler = new Handler();
 holder = surfaceView.getHolder();
 tingZhi_bt.setOnClickListener(this);
 auto_focus.setOnClickListener(this);
 screenshot.setOnClickListener(this);
 // 添加回调
 holder.addCallback(this);
 }

 /**
 * 将Camera和mediaRecoder释放
 */
 @Override
 protected void onDestroy() {
 handler.removeCallbacks(timeRun);
 if (mRecorder != null) {
  mRecorder.release();
 }
 if (myCamera != null) {
  myCamera.stopPreview();
  myCamera.release();
 }
 super.onDestroy();
 }

 /**
 * 控件点击事件的监听
 */
 @Override
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.luXiang_bt: // 录像点击事件
  if (!recording) {
  try {
   // 获取当前时间,作为视频文件的文件名
   String nowTime = java.text.MessageFormat.format(
    "{0,date,yyyyMMdd_HHmmss}",
    new Object[] { new java.sql.Date(System
     .currentTimeMillis()) });
   // 声明视频文件对象
   videFile = new File(videoFolder.getAbsoluteFile()
    + File.separator + "video" + nowTime + ".mp4");
   // 关闭预览并释放资源
   myCamera.unlock();
   mRecorder = new MediaRecorder();
   mRecorder.setCamera(myCamera);
   // 创建此视频文件
   videFile.createNewFile();
   mRecorder.setPreviewDisplay(surfaceView.getHolder()
    .getSurface()); // 预览
   mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 视频源
   mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 录音源为麦克风
   mRecorder
    .setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 输出格式为mp4
   /**
    *引用android.util.DisplayMetrics 获取分辨率
   */
   // DisplayMetrics dm = new DisplayMetrics();
   // getWindowManager().getDefaultDisplay().getMetrics(dm);
   mRecorder.setVideoSize(800, 480); // 视频尺寸
   mRecorder.setVideoEncodingBitRate(2*1280*720); //设置视频编码帧率
   mRecorder.setVideoFrameRate(30); // 视频帧频率
   mRecorder
    .setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); // 视频编码
   mRecorder
    .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 音频编码
   mRecorder.setMaxDuration(1800000); // 设置最大录制时间
   mRecorder.setOutputFile(videFile.getAbsolutePath()); // 设置录制文件源
   mRecorder.prepare(); // 准备录像
   mRecorder.start(); // 开始录像
   time_tv.setVisibility(View.VISIBLE); // 设置文本框可见
   handler.post(timeRun); // 调用Runable
   recording = true; // 改变录制状态为正在录制
   setAutofocus();
  } catch (IOException e1) {
   e1.printStackTrace();
  } catch (IllegalStateException e) {
   e.printStackTrace();
  }
  } else
  Toast.makeText(MainActivity.this, "视频正在录制中...",
   Toast.LENGTH_LONG).show();
  break;
 case R.id.tingZhi_bt: // 停止点击事件
  if (recording) {
  mRecorder.stop();
  mRecorder.release();
  handler.removeCallbacks(timeRun);
  time_tv.setVisibility(View.GONE);
  int videoTimeLength = time;
  time = 0;
  recording = false;
  Toast.makeText(
   MainActivity.this,
   videFile.getAbsolutePath() + " " + videoTimeLength
    + "秒", Toast.LENGTH_LONG).show();
  }
  // 开启相机
  if (myCamera == null) {
  myCamera = Camera.open();
  try {
   myCamera.setPreviewDisplay(holder);
  } catch (IOException e) {
   e.printStackTrace();
  }
  }
  myCamera.startPreview(); // 开启预览
  break;
 case R.id.auto_focus:
  setAutofocus();
  break;
 case R.id.screenshot:
  myCamera.autoFocus(new AutoFocusCallback() {

  @Override
  public void onAutoFocus(boolean success, Camera camera) {
   if (success) {
   camera.takePicture(null, null, jpegCallBack);
   }
  }
  });
  break;
 }
 }

 /**
 * 设置自动对焦
 */
 private void setAutofocus() {
 if (myCamera != null) {
  myCamera.autoFocus(new AutoFocusCallback() {
  @Override
  public void onAutoFocus(boolean success, Camera camera) {
   if (success) {
   }
  }
  });
 }
 }

 /**
 * 传感器改变调用的方法
 */
 @Override
 public void onSensorChanged(SensorEvent event) {
 if (event.sensor == null) {
  return;
 }
 if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
  int x = (int) event.values[0];
  int y = (int) event.values[1];
  int z = (int) event.values[2];
  calendar = Calendar.getInstance();
  long stamp = calendar.getTimeInMillis();
  int px = Math.abs(mX - x);
  int py = Math.abs(mY - y);
  int pz = Math.abs(mZ - z);
  int maxValue = getMaxValue(px, py, pz);
  if (maxValue > 2 && (stamp - lasttimestamp) > 30) {
  lasttimestamp = stamp;
  setAutofocus();
  }
  mX = x;
  mY = y;
  mZ = z;
 }
 }

 /**
 * 获取最大改变的值
 */
 private int getMaxValue(int px, int py, int pz) {
 int max = 0;
 if (px > py && px > pz) {
  max = px;
 } else if (py > px && py > pz) {
  max = py;
 } else if (pz > px && pz > py) {
  max = pz;
 }
 return max;
 }

 @Override
 public void onAccuracyChanged(Sensor sensor, int accuracy) {

 }

 /**
 * suraceView 创建执行的操作
 */
 @Override
 public void surfaceCreated(SurfaceHolder holder) {
 // 开启相机
 if (myCamera == null) {
  myCamera = Camera.open();
  try {
  myCamera.setPreviewDisplay(holder);
  } catch (IOException e) {
  e.printStackTrace();
  }
 }
 }

 /**
 * suraceView 状态改变执行的操作
 */
 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,
  int height) {
 // 开始预览
 myCamera.startPreview();
 Parameters parameters = myCamera.getParameters();// 获取mCamera的参数对象
 Size largestSize = getBestSupportedSize(parameters
  .getSupportedPreviewSizes());
 parameters.setPreviewSize(largestSize.width, largestSize.height);// 设置预览图片尺寸
 largestSize = getBestSupportedSize(parameters
  .getSupportedPictureSizes());// 设置捕捉图片尺寸
 parameters.setPictureSize(largestSize.width, largestSize.height);
 myCamera.setParameters(parameters);
 }

 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;
 } 

 /**
 * suraceView 销毁执行的操作
 */
 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
 // 关闭预览并释放资源
 if (myCamera != null) {
  myCamera.stopPreview();
  myCamera.release();
  myCamera = null;
 }
 }

 /**
 * 创建jpeg图片回调数据对象
 */
 private String filepath = "";
 private PictureCallback jpegCallBack = new PictureCallback() {
 @Override
 public void onPictureTaken(byte[] data, Camera camera) {

  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);
  filepath = Environment.getExternalStorageDirectory()
   + File.separator
   + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
   + ".jpg";
  File file = new File(filepath);
  try {
  BufferedOutputStream bos = new BufferedOutputStream(
   new FileOutputStream(file));
  newBitmap.compress(Bitmap.CompressFormat.JPEG, 85, bos);
  bos.flush();
  bos.close();
  camera.stopPreview();
  camera.startPreview();
  newBitmap.recycle();
  } catch (FileNotFoundException e) {
  e.printStackTrace();
  } catch (IOException e) {
  e.printStackTrace();
  }
 }
 };

}

xml布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:background="#ffffff" >

 <SurfaceView
 android:id="@+id/surfaceview"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"/> 

 <Button
 android:id="@+id/tingZhi_bt"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentRight="true"
 android:layout_alignParentBottom="true"
 android:text="停止"/>

 <Button
 android:id="@+id/luXiang_bt"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentBottom="true"
 android:layout_toLeftOf="@id/tingZhi_bt"
 android:text="录像"/>

 <Button
 android:id="@+id/auto_focus"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentBottom="true"
 android:layout_toLeftOf="@id/luXiang_bt"
 android:text="调焦"/>

 <Button
 android:id="@+id/screenshot"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentBottom="true"
 android:layout_toLeftOf="@id/auto_focus"
 android:text="拍照"/>

 <TextView
 android:id="@+id/time"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:textColor="#FF0000"
 android:text="1秒"
 android:visibility="gone"
 android:layout_alignParentBottom="true"
 android:layout_centerHorizontal="true"
 android:layout_marginBottom="10dp"/>

</RelativeLayout>

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

(0)

相关推荐

  • Android自定义Camera实现拍照功能

    本文记录了用自定义Camera实现的简单拍照功能. Camera类在5.0以后不推荐使用了,取而代之的是android.hardware.camera2包下的类,本文使用Camera. 我们首先自定义一个View去继承SurfaceView: public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.AutoFocusCallback { private Surface

  • android自定义Camera拍照并查看图片

    本文实例为大家分享了android自定义Camera拍照并查看图片的具体代码,供大家参考,具体内容如下 1.打开相机 a.预览拍摄图片,需用到SurfaceView,并且实现其回调函数implements SurfaceHolder.Callback: activity_camera.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http:/

  • Android中使用Camera类编写手机拍照App的实例教程

    Camera是Android摄像头硬件的相机类,位于硬件包"android.hardware.Camera"下.它主要用于摄像头捕获图片.启动/停止预览图片.拍照.获取视频帧等,它是设备本地的服务,负责管理设备上的摄像头硬件. Camera既然用于管理设备上的摄像头硬件,那么它也为开发人员提供了相应的方法,并且这些方法大部分都是native的,用C++在底层实现,下面简单介绍一下Camera的一些方法: static Camera open():打开Camera,返回一个Camera实

  • android之camera用法实例详解

    本文实例讲述了android之camera用法.分享给大家供大家参考.具体如下: 1.关于预览横竖差90度的问题 原因分析 经过查证和实验,可以证实:Android提供的SDK(android.hardware.Camera)里大概不能正常的使用竖屏(portrait layout)加载照相机,当用竖屏模式加载照相机时会产生以下情况: ①. 照相机成像左倾90度(倾斜): ②. 照相机成像长宽比例不对(失比). 之所以是"大概",原因是因为可能可以通过一些比较复杂的手段解决.如果以上成

  • Android 2.3.7.r1 camera录像过程中按menu菜单键时会停止录像

    Android 2.3.7.r1 按menu键时会停止录像.改成录像时按menu键不做处理,可做如下修改: 在packages/apps/CameraOpen/src/com/mediatek/camera/VideoCamera.java onKeyDown()方法中: 修改 复制代码 代码如下: case KeyEvent.KEYCODE_MENU: if (mHeadUpDisplay != null && mGLRootView != null && !mAlert

  • android系统在静音模式下关闭camera拍照声音的方法

    话说为了防止偷拍,业内有不成文规定,手机公司在做camera时,点击拍照和录像键的时候,必须要有提示音.因此,google也就非常人性化的将播放拍照声音的函数,放到了cameraService中,防止开发者能开发出不响的camera,从而只要调用拍照函数,一定会响,这是写死在framework中的. 话说这个规定在当今有点不合时宜,这不,今天我收到测试提的一个BUG,说是公司的新需求,要求在静音模式下拍照声音也得取消.这么无耻的需求,也许就在我们中国最大的山寨手机公司才会提到.废话不多说,看看是

  • Android camera实时预览 实时处理,人脸识别示例

    Android camera实时预览 实时处理,面部认证. 预览操作是网友共享的代码,我在继承SurfaceView 的CameraSurfaceView 中加入了帧监听事件,每次预览监听前五个数据帧,在处理做一个面部识别. 先看目录关系 自定义控件CameraSurfaceView.java 自定义接口方法CameraInterface.java CameraActivity预览界面. CameraSurfaceView.Java package com.centaur.camera.prev

  • Android Camera实现毫秒级拍照实例

    我们知道自定义Camera需要以下几步 打开相机,即实例化Camera对象,Camera camera = Camera.open(); 设置Camera的相关参数,Camera.Parameters parameters = camera.getParameters(); 打开预览,camera.setPreviewDisplay(surfaceholder); camera.startPreview(); 获取图片,这里只是从预览中获取因此使用,camera.setPreviewCallb

  • Android实现Camera2预览和拍照效果

    简介 网上对于 Camera2 的介绍有很多,在 Github 上也有很多关于 Camera2 的封装库,但是对于那些库,封装性太强,有时候我们仅仅是需要个简简单单的拍照功能而已,因此,自定义一个 Camera 使之变得轻量级那是非常重要的了.(本文并非重复造轮子, 而是在于学习 Camera2API 的基本功能, 笔记之.) 学习要点: 使用 Android Camera2 API 的基本功能. 迭代连接到设备的所有相机的特征. 显示相机预览和拍摄照片. Camera2 API 为连接到 An

  • Android编程中调用Camera时预览画面有旋转问题的解决方法

    本文实例讲述了Android编程中调用Camera时预览画面有旋转问题的解决方法.分享给大家供大家参考,具体如下: 在调用Camera写应用的时候,前后摄像头的情况有时候是不一样的.有时候,明明后摄像头没有问题,而调用到前摄像头时,却倒转了180°,或者其他角度,百思不得其解.在查看了Android源码之后,发现它的解决办法很是好,接下来贴个源码,以备日后查看. public static int getDisplayRotation(Activity activity) { int rotat

随机推荐