Android实现调用摄像头拍照与视频功能

作者:Hoking 时间:2021-11-22 08:02:28 

应用场景:

在Android开发过程中,有时需要调用手机自身设备的功能,上篇文章主要侧重摄像头拍照功能的调用。本篇文章将综合实现拍照与视频的操作。

知识点介绍:

该部分请阅读 【Android 调用摄像头功能】

使用方式:

第一步:

新建一个Android项目CameraPhotoVedio,包含两个Activity: MainActivity、CameraActivity。

第二步:

activity_main.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/shape_main"
tools:context=".MainActivity" >

<LinearLayout android:layout_height="wrap_content"
 android:layout_marginTop="50dp"
 android:layout_width="match_parent"
 android:orientation="vertical">
 <ImageView android:layout_height="wrap_content"
  android:layout_width="wrap_content"
  android:layout_gravity="center"
  android:src="@drawable/main"/>
</LinearLayout>
<LinearLayout android:layout_height="wrap_content"
 android:layout_marginTop="100dp"
 android:layout_width="match_parent"
 android:layout_alignParentBottom="true"
 android:orientation="vertical">
 <Button
  android:id="@+id/main_button"
  android:layout_height="50dp"
  android:layout_marginBottom="50dp"
  android:background="@drawable/shape_main"
  android:layout_width="match_parent"
  android:textColor="#FFFFFF"
  android:text="使用摄像头"/>
</LinearLayout>
</RelativeLayout>

MainActivity.java


import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

private Button button; //调用摄像头按钮

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 initViews();
}

private void initViews() {
 button = (Button) findViewById(R.id.main_button);
 button.setOnClickListener(new OnClickListener() {

@Override
  public void onClick(View v) {
   startActivity(new Intent(getApplicationContext(), CameraActivity.class));
  }
 });
}
}

activity_camera.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#FFFFFF"
android:layout_height="match_parent"
tools:context=".CameraActivity" >
<SurfaceView
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:id="@+id/camera_surfaceview"/>
<TextView android:layout_height="wrap_content"
 android:layout_width="wrap_content"
 android:text="计时区域"
 android:id="@+id/camera_time"/>
<LinearLayout android:layout_height="wrap_content"
 android:layout_width="match_parent"
 android:layout_alignParentBottom="true"
 android:orientation="horizontal">
 <Button android:layout_height="30dp"
  android:layout_width="match_parent"
  android:layout_marginBottom="20dp"
  android:layout_weight="1"
  android:background="@drawable/shape_main"
  android:id="@+id/camera_photo"
  android:layout_marginLeft="5dp"
  android:textColor="#FFFFFF"
  android:layout_marginRight="5dp"
  android:text="照片摄取"/>
 <Button android:layout_height="30dp"
  android:layout_marginBottom="20dp"
  android:layout_width="match_parent"
  android:layout_weight="1"
  android:background="@drawable/shape_main"
  android:id="@+id/camera_vedio"
  android:layout_marginLeft="5dp"
  android:textColor="#FFFFFF"
  android:layout_marginRight="5dp"
  android:text="视频摄取"/>
</LinearLayout>
</RelativeLayout>

CameraActivity.java


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import com.example.cameraphotovideo.utils.FormatUtil;

import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.app.Activity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class CameraActivity extends Activity {

private String tag ="MaHaochen_______CameraActivity";
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Camera camera;
private MediaRecorder mediaRecorder;
private Button photoButton; //拍照按钮
private Button vedioButton; //摄像按钮
private TextView timeTextView;

protected boolean isPreview = false; //摄像区域是否准备良好
private boolean isRecording = true; // true表示没有录像,点击开始;false表示正在录像,点击暂停
private boolean bool;

private int hour = 0;
private int minute = 0;  //计时专用
private int second = 0;

private File mRecVedioPath;
private File mRecAudioFile;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_camera);
 initCamera();
 initViews();
}
//初始化摄像头
private void initCamera() {
 mRecVedioPath = new File(Environment.getExternalStorageDirectory()
   .getAbsolutePath() + "/mahc/video/temp/");
 if (!mRecVedioPath.exists()) {
  mRecVedioPath.mkdirs();
 }
 surfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview);
 SurfaceHolder cameraSurfaceHolder = surfaceView.getHolder();
 cameraSurfaceHolder.addCallback(new Callback() {

@Override
  public void surfaceCreated(SurfaceHolder holder) {
   try {
   camera = Camera.open();
   //设置Camera的角度/方向
   camera.setDisplayOrientation(90);
   Camera.Parameters parameters = camera.getParameters();
   parameters.setPreviewFrameRate(5); // 每秒5帧
   parameters.setPictureFormat(ImageFormat.JPEG);// 设置照片的输出格式
   parameters.set("jpeg-quality", 85);// 照片质量
   camera.setParameters(parameters);
   camera.setPreviewDisplay(holder);
   isPreview = true;
   camera.startPreview();
   } catch (IOException e) {
    e.printStackTrace();
   }
   surfaceHolder = holder;
  }

@Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width,
    int height) {
   surfaceHolder = holder;
  }

@Override
  public void surfaceDestroyed(SurfaceHolder holder) {
   if (camera != null) {
    if (isPreview) {
     camera.stopPreview();
     isPreview = false;
    }
    camera.release();
    camera = null; // 记得释放Camera
   }
   surfaceView = null;
   surfaceHolder = null;
   mediaRecorder = null;
  }
 });
 //开发时建议设置
 //This method was deprecated in API level 11. this is ignored, this value is set automatically when needed.
 cameraSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

//初始化视图组件
private void initViews() {
 timeTextView = (TextView) findViewById(R.id.camera_time);
 timeTextView.setVisibility(View.GONE);
 photoButton = (Button) findViewById(R.id.camera_photo);
 vedioButton = (Button) findViewById(R.id.camera_vedio);
 ButtonOnClickListener onClickListener = new ButtonOnClickListener();
 photoButton.setOnClickListener(onClickListener);
 vedioButton.setOnClickListener(onClickListener);
}

class ButtonOnClickListener implements OnClickListener{

@Override
 public void onClick(View v) {
  switch (v.getId()) {
  case R.id.camera_vedio:
   //点击开始录像
   if(isRecording){
    if (isPreview) {
     camera.stopPreview();
     camera.release();
     camera = null;
    }
    second = 0;
    minute = 0;
    hour = 0;
    bool = true;
    if(null==mediaRecorder){
     mediaRecorder = new MediaRecorder();
    }else {
     mediaRecorder.reset();
    }
    //表面设置显示记录媒体(视频)的预览
    mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
    //开始捕捉和编码数据到setOutputFile(指定的文件)
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    //设置用于录制的音源
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    //设置在录制过程中产生的输出文件的格式
    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    //设置视频编码器,用于录制
    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    //设置audio的编码格式
    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    //设置要捕获的视频的宽度和高度
    mediaRecorder.setVideoSize(320, 240);
    // 设置要捕获的视频帧速率
    mediaRecorder.setVideoFrameRate(15);
    try {
     mRecAudioFile = File.createTempFile("Vedio", ".3gp",
       mRecVedioPath);
    } catch (IOException e) {
     e.printStackTrace();
    }
    mediaRecorder.setOutputFile(mRecAudioFile.getAbsolutePath());
    try {
     mediaRecorder.prepare();
     timeTextView.setVisibility(View.VISIBLE);
     handler.postDelayed(task, 1000);
     mediaRecorder.start();
    } catch (Exception e) {
     e.printStackTrace();
    }
    isRecording = !isRecording;
    Log.e(tag, "=====开始录制视频=====");
   }else {
    //点击停止录像
    bool = false;
    mediaRecorder.stop();
    timeTextView.setText(FormatUtil.format(hour)+":"+FormatUtil.format(minute)+":"+ FormatUtil.format(second));
    mediaRecorder.release();
    mediaRecorder = null;
    FormatUtil.videoRename(mRecAudioFile);
    Log.e(tag, "=====录制完成,已保存=====");
    isRecording = !isRecording;
    try {
     camera = Camera.open();
     Camera.Parameters parameters = camera.getParameters();
//      parameters.setPreviewFrameRate(5); // 每秒5帧
     parameters.setPictureFormat(ImageFormat.JPEG);// 设置照片的输出格式
     parameters.set("jpeg-quality", 85);// 照片质量
     camera.setParameters(parameters);
     camera.setPreviewDisplay(surfaceHolder);
     camera.startPreview();
     isPreview = true;
    } catch (Exception e) {
     e.printStackTrace();
    }
   }
   break;

case R.id.camera_photo:
   if (mediaRecorder != null) {
    try {
     bool = false;
     mediaRecorder.stop();
     timeTextView.setText(FormatUtil.format(hour) + ":" + FormatUtil.format(minute) + ":"
       + FormatUtil.format(second));
     mediaRecorder.release();
     mediaRecorder = null;
     FormatUtil.videoRename(mRecAudioFile);
    } catch (Exception e) {
     e.printStackTrace();
    }
    isRecording = !isRecording;
    Log.e(tag, "=====录制完成,已保存=====");
    try {
     camera = Camera.open();
     Camera.Parameters parameters = camera.getParameters();
//      parameters.setPreviewFrameRate(5); // 每秒5帧
     parameters.setPictureFormat(ImageFormat.JPEG);// 设置照片的输出格式
     parameters.set("jpeg-quality", 85);// 照片质量
     camera.setParameters(parameters);
     camera.setPreviewDisplay(surfaceHolder);
     camera.startPreview();
     isPreview = true;
    } catch (Exception e) {
     e.printStackTrace();
    }
   }
   if (camera != null) {
    camera.autoFocus(null);
    camera.takePicture(null, null, new PictureCallback() {
     @Override
     public void onPictureTaken(byte[] data, Camera camera) {
      new SavePictureTask().execute(data);
      camera.startPreview();
      Log.e(tag,"=====拍照成功=====");
     }
    }); // 拍照
   }
   break;
  default:
   break;
  }
 }
}
/*
 * 定时器设置,实现计时
 */
private Handler handler = new Handler();
private Runnable task = new Runnable() {
 public void run() {
  if (bool) {
   handler.postDelayed(this, 1000);
   second++;
   if (second >= 60) {
    minute++;
    second = second % 60;
   }
   if (minute >= 60) {
    hour++;
    minute = minute % 60;
   }
   timeTextView.setText(FormatUtil.format(hour) + ":" + FormatUtil.format(minute) + ":"
     + FormatUtil.format(second));
  }
 }
};

class SavePictureTask extends AsyncTask<byte[], String, String> {
 @Override
 protected String doInBackground(byte[]... params) {
  String path = Environment.getExternalStorageDirectory()
    .getAbsolutePath() + "/mahc/image";
  File out = new File(path);
  if (!out.exists()) {
   out.mkdirs();
  }
  File picture = new File(path+"/"+new Date().getTime()+".jpg");
  try {
   FileOutputStream fos = new FileOutputStream(picture.getPath());
   fos.write(params[0]);
   fos.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
  Log.e(tag, "=====照片保存完成=====");
  CameraActivity.this.finish();
  return null;
 }
}
}

第三步:该项目需要一个工具类FormatUtil.java


import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.os.Environment;

public class FormatUtil {

/**
 * 将缓存文件夹的数据转存到vedio文件下
 * @param recAudioFile
 */
public static void videoRename(File recAudioFile) {
 String path = Environment.getExternalStorageDirectory()
   .getAbsolutePath()+ "/mahc/video/"+ "0" + "/";
 String fileName = new SimpleDateFormat("yyyyMMddHHmmss")
   .format(new Date()) + ".3gp";
 File out = new File(path);
 if (!out.exists()) {
  out.mkdirs();
 }
 out = new File(path, fileName);
 if (recAudioFile.exists())
  recAudioFile.renameTo(out);
}

/**
 * 用以计时操作的相关方法
 * @param num
 * @return
 */
public static String format(int num){
 String s = num + "";
 if (s.length() == 1) {
  s = "0" + s;
 }
 return s;
}
}

第四步:本项目需要处理界面的背景样式和按钮的背景,所以需要在res/drawable文件新建shape_main.xml。


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
 android:startColor="#FFCC99"
 android:endColor="#99CC66"
 android:centerColor="#0066CC"
 android:angle="45" />
</shape>

页面效果:

效果截图

Android实现调用摄像头拍照与视频功能

下载地址:Android实现调用摄像头拍照与视频功能

来源:https://blog.csdn.net/mahoking/article/details/28292973

标签:Android,摄像头,拍照,视频
0
投稿

猜你喜欢

  • springBoot项目中使用@Value取值出现的问题及解决

    2023-05-29 12:59:16
  • Android自定义View实现绘制虚线的方法详解

    2022-06-24 01:18:10
  • Mybatis中的resultType和resultMap查询操作实例详解

    2022-02-24 17:05:42
  • idea的使用之关于tomcat热部署的教程

    2022-12-02 20:16:46
  • C# wpf 通过HwndHost渲染视频的实现方法

    2023-08-30 03:33:35
  • Java反射及性能详细

    2023-08-20 20:49:42
  • C#后台接受前台JSON字符串装换成字典集合处理

    2023-07-03 02:38:55
  • 实例详解SpringBoot默认的JSON解析方案

    2023-07-21 07:34:20
  • Android Studio实现简易计算器设计

    2022-08-22 18:41:55
  • Spring+Junit4进行接口测试实例代码

    2021-09-15 07:44:06
  • Springboot打成war包并在tomcat中运行的部署方法

    2022-06-29 07:53:32
  • Java中间消息件ActiveMQ使用实例

    2021-10-10 14:24:21
  • java中利用List的subList方法实现对List分页(简单易学)

    2022-06-18 23:33:09
  • 通过c++11改进我们的模式之改进命令模式

    2023-03-02 01:58:00
  • 如何在Redis中实现分页排序查询过程解析

    2022-04-13 12:08:15
  • C#中的除法运算符与VB.NET中的除法运算符

    2022-04-01 10:52:56
  • C#判断一天、一年已经过了百分之多少的方法

    2022-07-16 15:23:11
  • Android刮刮卡功能具体实现代码

    2021-08-06 04:12:24
  • Android 中自定义Dialog样式的Activity点击空白处隐藏软键盘功能(dialog不消失)

    2022-03-10 12:15:21
  • java 使用DecimalFormat进行数字的格式化实例详解

    2022-04-28 10:55:25
  • asp之家 软件编程 m.aspxhome.com