我们了解了视频相关的基础知识,后面的文章我们要能够和音频一样可以采集我们的视频,视频是一帧一帧的图片来的,我们首先要学习预览视频,然后采集一帧图片,采集视频从简到难的来了解这个问题。首先第一个反应打开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" />...<uses-feature android:name="android.hardware.location.gps" />

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

拍照

请求摄像头特征

... >    "android.hardware.camera"                  android:required="true" />    ...

这个权限可以让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上面

@Overrideprotected 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。

...>    "android.permission.WRITE_EXTERNAL_STORAGE" />    ...

开始重新请求拍照代码

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

   ...   "android.support.v4.content.FileProvider"        android:authorities="com.example.android.fileprovider"        android:exported="false"        android:grantUriPermissions="true">        "android.support.FILE_PROVIDER_PATHS"            android:resource="@xml/file_paths">        ...

在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链接查看

更多相关文章

  1. Android 9.0 关于ACTION_CALL无权限导致闪退的问题
  2. Android中抓取手机视频流数据。
  3. Android操作系统安全(分层结构、应用沙盒、安全进程通信、Android
  4. Android4.2也能视频通讯啦!最新应用附代码分享
  5. Android 6.0 运行时权限的处理
  6. 基于Android的远程视频监控系统(含源码)
  7. [转]android 安全与权限(Security and Permissions)(翻译)
  8. 认识Android的UID(Unix user ID)与权限
  9. Android实现选择视频功能

随机推荐

  1. Android(安卓)Debug Bridge (adb)
  2. Android(安卓)中下载文件到sdcard和进度
  3. Android中使用webview加载网页上的按钮点
  4. Android高性能加载大量图片[前言]
  5. Android监听器实现(二)Broadcast方式对通
  6. Android(安卓)原生微博分享网络图片
  7. 利用Ant编译android工程
  8. Android中用AsyncTask简单实现多线程
  9. 成为更好的Android开发者的30多个技巧
  10. Android基础和运行机制