Android音视频之视频采集(系统API预览)

我们了解了视频相关的基础知识,后面的文章我们要能够和音频一样可以采集我们的视频,视频是一帧一帧的图片来的,我们首先要学习预览视频,然后采集一帧图片,采集视频从简到难的来了解这个问题。首先第一个反应打开Google搜索和Android视频采集相关的东西,我们要知道如何通过API来采集,不由自主地到了Android官网的Camera API。Android有两个视频采集的API,Camera是Android 5.0以前使用的,现在已经废弃了,我们还是得学一下他的使用,Camera2是最新的视频采集API,我们重点了解它的使用。这篇文章我们掌握调用系统的拍照和录制视频API来实现拍照录像功能。

Camera

它是API21(Android5.0)以前用来对摄像头数据采集的的API,我们从开始到每个环节的关键内容记录如下。

基础知识

先来了解使用Camera有几个相关联的类。
Camera:API21以后老的API控制摄像头设备
SurfaceView:显示摄像头预览图像给用户
MediaRecorder:录制摄像头的视频

权限声明

摄像头权限:我们要使用Camera设备必须要声明一个权限

<uses-permission android:name="android.permission.CAMERA" />

但是当我们使用Intent来调用系统自己的Camera设备拍照录像就不需要这个权限。
摄像头特征:应用必须声明使用摄像头特性权限(这个不知道是啥意思的要了解uses-feature这个清单文件的意义)

<uses-feature android:name="android.hardware.camera" />

音频录制权限:当录制视频的时候我们还要音频就要加上这个权限。

<uses-permission android:name="android.permission.RECORD_AUDIO" />

存储权限:如果我们要保存相片和视频在存储设备那么就要加上这个权限。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

定位权限:如果照片的标签要GPS位置信息,我们就要如下权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
...
<!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
<uses-feature android:name="android.hardware.location.gps" />

调用系统的摄像头app来拍照和录制视频

拍照

请求摄像头特征

<manifest ... >
 <uses-feature android:name="android.hardware.camera"
     android:required="true" />
 ...
</manifest>

这个权限可以让GooglePlay来判断是否设备支持下载我们的应用,如果设置required为true那么一定要有摄像头硬件设备的才能下载,如果设置required为false,那么没有摄像头硬件设备的也可以下载,当然我们在程序里面就要判断一下是否有摄像头可用了。

使用默认Intent开始拍照

调用默认的开启系统拍照App的Intent

static final int REQUEST_IMAGE_CAPTURE = 1;

private void dispatchTakePictureIntent() {
 Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
  startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
 }
}

获取拍照图片

我们刚才通过startActivityForResult来拍照了,很自然的在onActivityResult来接受返回的数据,我们把图片显示在一个ImageView上面

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
  Bundle extras = data.getExtras();
  Bitmap imageBitmap = (Bitmap) extras.get("data");
  mImageView.setImageBitmap(imageBitmap);
 }
}

通过这种默认的拍照我们不需要在Android6.0以上的机器声明任何权限就可以成功执行。

自定义保存相片图片路径

我们上面的操作,获取来的是一个bitmap,我们的图片信息都是在内存里面操作的,如果我们要保存拍照的图片到存储卡并且查看图片,那么我们只要声明一个写存储卡权限就OK。

<manifest ...>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 ...
</manifest>

开始重新请求拍照代码

static final int REQUEST_TAKE_PHOTO = 1;

private void dispatchTakePictureIntent() {
 Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 // Ensure that there's a camera activity to handle the intent
 if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
  // Create the File where the photo should go
  File photoFile = null;
  try {
   photoFile = createImageFile();
  } catch (IOException ex) {
   // Error occurred while creating the File
   ...
  }
  // Continue only if the File was successfully created
  if (photoFile != null) {
   Uri photoURI = FileProvider.getUriForFile(this,
             "com.example.android.fileprovider",
             photoFile);
   takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
   startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
  }
 }
}

String mCurrentPhotoPath;

private File createImageFile() throws IOException {
 // Create an image file name
 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
 String imageFileName = "JPEG_" + timeStamp + "_";
 File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
 File image = File.createTempFile(
  imageFileName, /* prefix */
  ".jpg",   /* suffix */
  storageDir  /* directory */
 );

 // Save a file: path for use with ACTION_VIEW intents
 mCurrentPhotoPath = image.getAbsolutePath();
 return image;
}

上面的代码我们使用了FileProvider.getUriForFile方法,它返回content://URI,这个API在Android7.0以上使用不做处理会抛出FileUriExposedException。我们要在清单文件注册配置一个FileProvider

<application>
 ...
 <provider
  android:name="android.support.v4.content.FileProvider"
  android:authorities="com.example.android.fileprovider"
  android:exported="false"
  android:grantUriPermissions="true">
  <meta-data
   android:name="android.support.FILE_PROVIDER_PATHS"
   android:resource="@xml/file_paths"></meta-data>
 </provider>
 ...
</application>

在res/xml/file_paths配置文件

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
 <external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>

添加照片到相册

我们上面的照片保存位置根目录为getExternalFilesDir(Environment.DIRECTORY_PICTURES);这个目录下面多媒体扫描器是不能找到我们的照片的,因为它是我们App私有的。下面的代码可以让系统的多媒体扫描器添加我们的图片到Media Provider's 数据库,让我们的图片对系统相册和其他应用都可以使用。

private void galleryAddPic() {
  Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
  File f = new File(mCurrentPhotoPath);
  try {
   MediaStore.Images.Media.insertImage(getContentResolver(),
     f.getAbsolutePath(), f.getName(), null);
   Log.d(TAG, "galleryAddPic: add to Media Scanner success");
  } catch (FileNotFoundException e) {
   e.printStackTrace();
   Log.e(TAG, "galleryAddPic: add to Media Scanner failed");
  }

  Uri contentUri = Uri.fromFile(f);
  mediaScanIntent.setData(contentUri);
  this.sendBroadcast(mediaScanIntent);
  Toast.makeText(this, "Add to Gallery success", Toast.LENGTH_SHORT).show();
 }

解码缩放图片

我们在把图片ImageView上面,没有做任何处理,如果图片较大,会导致oom的,做一个缩放处理。

private void setPic() {
 // Get the dimensions of the View
 int targetW = mImageView.getWidth();
 int targetH = mImageView.getHeight();

 // Get the dimensions of the bitmap
 BitmapFactory.Options bmOptions = new BitmapFactory.Options();
 bmOptions.inJustDecodeBounds = true;
 BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
 int photoW = bmOptions.outWidth;
 int photoH = bmOptions.outHeight;

 // Determine how much to scale down the image
 int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

 // Decode the image file into a Bitmap sized to fill the View
 bmOptions.inJustDecodeBounds = false;
 bmOptions.inSampleSize = scaleFactor;
 bmOptions.inPurgeable = true;

 Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
 mImageView.setImageBitmap(bitmap);
}

demo代码参考

录像

录制视频播放的代码很简单,如果要对视频播放器进行定制,那么久要多一些东西,我们现在只简单的可以播放调用系统录制的视频。

开启视频录制Intent

static final int REQUEST_VIDEO_CAPTURE = 1;

private void dispatchTakeVideoIntent() {
 Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
 if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
  startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
 }
}

在onActivityResult里面接收视频Uri来播放

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
  if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
   Uri videoUri = intent.getData();
   Log.d(TAG, "onActivityResult: " + videoUri);
   mVideoView.setVideoURI(videoUri);
   mVideoView.requestFocus();
   mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

    @Override
    public void onPrepared(MediaPlayer mp) {
     mp.setLooping(false);//设置视频重复播放
    }
   });
   mVideoView.start();//播放视频
   MediaController mediaController = new MediaController(this);//显示控制条
   mVideoView.setMediaController(mediaController);
   mediaController.setMediaPlayer(mVideoView);//设置控制的对象
   mediaController.show();
  }
 }

demo链接查看

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

(0)

相关推荐

  • android采用FFmpeg实现音视频合成与分离

    上一篇文章谈到音频剪切.混音.拼接与转码,也详细介绍cMake配置与涉及FFmpeg文件的导入: android端采用FFmpeg进行音频混合与拼接剪切.现在接着探讨音视频的合成与分离. 1.音频提取 从多媒体文件中提取音频,关键命令为"-acodec copy -vn",其中"-acodec copy"是采用音频编码器拷贝音频流,"-vn"是去掉video视频流: /** * 使用ffmpeg命令行进行抽取音频 * @param srcFile

  • Android提高之MediaPlayer音视频播放

    前面文章已经详细介绍了Android界面的入门技术,相信大家在看完和跟着练习之后,会对于常用的Layout和View都会有一定的了解了,接下来就不再强调介绍界面了,而是针对具体的常见功能而展开. 本文将介绍MediaPlayer的使用.MediaPlayer可以播放音频和视频,另外也可以通过VideoView来播放视频,虽然VideoView比MediaPlayer简单易用,但定制性不如用MediaPlayer,这需要视情况选择.MediaPlayer播放音频比较简单,但是要播放视频就需要Sur

  • Android中音视频合成的几种方案详析

    前言 最近工作中遇到了音视频处理的需求,Android下音视频合成,在当前调研方案中主要有三大类方法:MediaMux硬解码,mp4parser,FFmepg.三种方法均可实现,但是也有不同的局限和问题,先将实现和问题记录于此,便于之后的总结学习.下面话不多说了,来一起看看详细的介绍吧. 方法一(Fail) 利用MediaMux实现音视频的合成. 效果:可以实现音视频的合并,利用Android原生的VideoView和SurfaceView播放正常,大部分的播放器也播放正常,但是,但是,在上传Y

  • Android音视频之视频采集(系统API预览)

    我们了解了视频相关的基础知识,后面的文章我们要能够和音频一样可以采集我们的视频,视频是一帧一帧的图片来的,我们首先要学习预览视频,然后采集一帧图片,采集视频从简到难的来了解这个问题.首先第一个反应打开Google搜索和Android视频采集相关的东西,我们要知道如何通过API来采集,不由自主地到了Android官网的Camera API.Android有两个视频采集的API,Camera是Android 5.0以前使用的,现在已经废弃了,我们还是得学一下他的使用,Camera2是最新的视频采集A

  • Android实现疯狂连连看游戏之游戏效果预览(一)

    今天看完了李刚老师的<疯狂Android讲义>一书中的第18章<疯狂连连看>,从而学会了如何编写一个简单的Android疯狂连连看游戏. 开发这个流行的小游戏,难度适中,而且能充分激发学习热情,适合Android初学者来说是一个不错的选择.对于该游戏的开发,需要重点掌握单机游戏的界面分析和数据建模能力:游戏玩家严重看到的是游戏界面,但是在开发者眼中看到的应该是数据模型.除此之外,单机游戏通常需要一个比较美观的界面,需要通过自定义View来实现游戏主界面. 开发连连看游戏除了需要理解

  • Android实现pdf在线预览或本地预览的方法

    最近项目中需要使用在线预览pdf,并要能实现自动播放,我想这样的需求无论如何来说都是很操蛋的 由于本人水平有限,最后讨论将项目需求改成将pdf下载到本地再实现自动播放. 接下来总结下目前能够实现pdf阅读的方案,开发当中需要根据实际需求去选择相应的方案. 1.使用Google doc支持来展示word,excel,pdf,txt(WebView方式在线预览): <span style="font-size:18px;">WebView urlWebView = (WebVi

  • Android音视频开发之MediaExtactor使用教程

    目录 前言 MediaExtactor 使用MediaExtactor 加载音视频文件代码 获取轨道代码 提取轨道数据信息 一些源码细节分析 前言 在之前学习如何使用MediaPlayer后,了解到Android系统提供开发者播放多媒体全家桶能力,但对于开发者希望DIY自由度更高的播放器能力也是可以利用Android内部提供组件包自行实现一个播放器的.举例实现一个视频播放这个流程,它大致流程是[多媒体文件解析提取视频文件]-> [视频流解码]-> [解码数据播放渲染到Render].首要需要实

  • Android音视频开发之MediaPlayer使用教程

    目录 MediaPlayer 简单使用 缺陷 AndroidMediaPlayer播放器封装 状态机编写 内部类 初始化函数 方法和回调 小结 MediaPlayer Android多媒体框架支持播放提供了MediaPlayerAPI,可以通过MediaPlayer来实现媒体文件播放.可以说MediaPlayer是非常方便使用的多媒体播放器,只需要简单设置就能实现对音频和视频播放功能,其内部帮助开发者实现了播放对象获取解码以及播放功能. 简单使用 MediaPlayer支持多种资源形式:本地资源

  • Android音视频开发之VideoView使用指南

    目录 VideoView介绍 MediaController 使用 源码分析 进度显示 播放尺寸适配 VideoView介绍 之前介绍过使用MediaPlayer+SurfaceView实现播放视频功能.无意间发现官方封装了VideoView组件来实现简单视频播放功能,内部同样是使用MediaPlayer+SurfaceView的形式控制MediaPlayer对视频文件进行播放.使用场景比较简单,适用于只是播放视频的场景,其提供能力有限不太适合使用在调节视频亮度等其他功能. MediaContr

  • Android使用MediaCodec将摄像头采集的视频编码为h264

    本文实例为大家分享了Android使用MediaCodec将摄像头采集的视频编码为h264,供大家参考,具体内容如下 MainActivity.java import android.app.Activity; import android.graphics.ImageFormat; import android.hardware.Camera; import android.hardware.Camera.Parameters; import android.hardware.Camera.P

  • Android 使用SwipeRefreshLayout控件仿抖音做的视频下拉刷新效果

    SwipeRefreshLayout(这个控件),我先跟大家介绍一下这个控件: 一.SwipeRefreshLayout简单介绍 •先看以下官方文档,已有了很详细的描述了. 官方文档说明 •这里我再大概解释一下: •在竖直滑动时想要刷新页面可以用SwipeRefreshLayout来实现.它通过设置OnRefreshListener来监听界面的滑动从而实现刷新.也可以通过一些方法来设置SwipeRefreshLayout是否可以刷新.如:setRefreshing(true),展开刷新动画. s

  • Android音视频开发之MediaCodec的使用教程

    目录 前言 MediaCodec 编解码流程 生命周期 接口简介 前言 获取到音视频轨道(编解码格式),知道设备支持哪些编解码器,下一步就是创建编解码器去实现数据流的编解码过程了.在Android开发中提供了实现音视频编解码工具MediaCodec,针对对应音视频解码类型通过该类创建对应解码器就能实现对数据进行解码操作. MediaCodec MediaCodec所支持的数据类型:压缩的音视频数据.原始音频数据和原始视频数据. 首先show代码,紧接着之前MediaExtactor提取资源,Me

  • Android音视频开发Media FrameWork框架源码解析

    目录 一.Media FrameWork背景 二.Media Framework“路线图” 2.1 代理端 2.2 服务端 2.2.1 Source 2.2.2 Decoder 2.2.3 Renderer 2.2.4 Foundation 2.3 OMX端 2.4 Kernel端 三.media播放的流程 四.Media FrameWork源码分析 一.Media FrameWork背景 Media Framework (媒体函数库):此函数库让Android 可以播放与录制许多常见的音频与视

随机推荐