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

 更新时间:2022年03月29日 07:52:59   作者:Hoking  
这篇文章主要为大家详细介绍了Android实现调用摄像头拍照与视频功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

应用场景:

在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控件SlidingMenu的实例代码

    简单仿写Android控件SlidingMenu的实例代码

    下面小编就为大家分享一篇简单仿写Android控件SlidingMenu的实例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • android指定DatePickerDialog样式并不显示年的实现代码

    android指定DatePickerDialog样式并不显示年的实现代码

    下面小编就为大家带来一篇android指定DatePickerDialog样式并不显示年的实现代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,祝大家游戏愉快哦
    2016-08-08
  • Kotlin编程基础数据类型示例详解

    Kotlin编程基础数据类型示例详解

    这篇文章主要为大家介绍了Kotlin编程基础数据类型示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • RecyclerView使用详解

    RecyclerView使用详解

    本文主要对RecyclerView的使用进行了详细介绍,文章结尾附上源码下载,具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • Android仿QQ消息提示实现弹出式对话框

    Android仿QQ消息提示实现弹出式对话框

    这篇文章主要为大家详细介绍了Android仿QQ消息提示实现弹出式对话框,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Android组件ContextMenu实现长按事件

    Android组件ContextMenu实现长按事件

    这篇文章主要为大家详细介绍了Android组件ContextMenu实现长按事件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • Android中ViewFlipper的使用及设置动画效果实例详解

    Android中ViewFlipper的使用及设置动画效果实例详解

    这篇文章主要介绍了Android中ViewFlipper的使用及设置动画效果的方法,以实例形式较为详细的分析了ViewFlipper的功能、原理及设置与使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • Android Studio使用教程(二):基本设置与运行

    Android Studio使用教程(二):基本设置与运行

    这篇文章主要介绍了Android Studio使用教程(二):基本设置与运行,本文讲解了项目结构、偏好设置、常用功能介绍、创建模拟器等内容,需要的朋友可以参考下
    2015-05-05
  • 详解Android代码混淆实战

    详解Android代码混淆实战

    这篇文章主要介绍了详解Android代码混淆实战,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Android编程实现动态支持多语言的方法

    Android编程实现动态支持多语言的方法

    这篇文章主要介绍了Android编程实现动态支持多语言的方法,涉及Android资源、控件及属性相关操作技巧,需要的朋友可以参考下
    2017-06-06

最新评论