总览
一.Camera
1.概述
通过Camera API 或摄像头意图Intent,Android框架为图像和视频捕获提供支持。下面列出了有关的类:
①Camera 此类是控制摄像头的主要API。在创建摄像头应用程序时,此类用于拍摄照片或视频。
②SurfaceView 此类用于向用户提供摄像头实时预览功能。
③MediaRecorder 此类用于从摄像头录制视频。
④Intent 动作类型为MediaStore.ACTION_IMAGE_CAPTURE 或MediaStore.ACTION_VIDEO_CAPTURE 的意图,可在不直接使用Camera对象的情况下捕获图像和视频。
2.所需权限声明
Camera权限——应用程序必须对请求摄像头的使用权限。
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
存储权限——如果应用程序要把图像或视频保存到设备的外部存储上(SD卡),则还必须在manifest中指定如下权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
录音权限——要用音频捕获来录音,应用程序必须请求音频捕获权限。
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
3.使用内置的摄像头应用程序
有一种快捷的方法可以让应用程序不用额外编写很多代码就能实现拍照或摄像,这就是用意图Intent来调用内置的Android摄像头应用程序。摄像头意图(intent)会请求通过内置摄像应用来捕获图像或视频,并把控制权返回给应用程序。
具体步骤
-
构建一个摄像头 Intent —— 用以下意图类型之一,创建一个请求图像或视频的Intent :
MediaStore.ACTION_IMAGE_CAPTURE —— 向内置摄像头程序请求图像的意图活动类型。
MediaStore.ACTION_VIDEO_CAPTURE —— 向内置摄像头程序请求视频的意图活动类型。
-
启动摄像头 Intent ——用startActivityForResult()方法执行摄像头 intent。启动完毕后摄像头应用的用户界面就会显示在屏幕上,用户就可以拍照或摄像了。
-
接收Intent结果 —— 在应用程序中设置onActivityResult()方法,用于接收从摄像头 intent返回的数据。当用户拍摄完毕后(或者取消操作),系统会调用此方法。
案例
调用摄像头进行拍照和进行拍视频
首先,权限声明
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
<uses-feature
android:name="android.hardware.Camera"
android:required="false"></uses-feature>
布局文件
<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.administrator.cameravideo.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="拍照"
android:onClick="imageCapture"
android:id="@+id/button"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="小视频"
android:onClick="videoCapture"
android:id="@+id/button2"
android:layout_below="@+id/button"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignRight="@+id/button"
android:layout_alignEnd="@+id/button" />
</RelativeLayout>
MainActivity.java
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.io.File;
public class MainActivity extends AppCompatActivity {
private static final int MEDIA_TYPE_IMAGE = 1;
private static final int MEDIA_TYPE_VIDEO = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//拍照
public void imageCapture(View view) {
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getOutputMediaFileUri(MEDIA_TYPE_IMAGE));
startActivityForResult(intent, MEDIA_TYPE_IMAGE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (resultCode) {
case RESULT_OK:
if (MEDIA_TYPE_IMAGE == requestCode) {
//图片
// Uri uri= data.getData();
System.out.println(file);
} else if (MEDIA_TYPE_VIDEO == requestCode) {
System.out.println(file);
System.out.println(data.getData());
}
break;
}
}
//录制视频
public void videoCapture(View view) {
Intent intent=new Intent();
intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,getOutputMediaFileUri(MEDIA_TYPE_VIDEO));
//第二个参数为视频质量
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,1);
startActivityForResult(intent,MEDIA_TYPE_VIDEO);
}
File file = null;
private Uri getOutputMediaFileUri(int type) {
file = getOutputMediaFile(type);
return Uri.fromFile(file);
}
private File getOutputMediaFile(int type) {
File file = null;
String rootPath = null;
switch (type) {
case MEDIA_TYPE_IMAGE:
rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath();
file = new File(rootPath + File.separator + System.currentTimeMillis() + ".jpg");
break;
case MEDIA_TYPE_VIDEO:
rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getPath();
file = new File(rootPath + File.separator + System.currentTimeMillis() + ".mp4");
break;
}
return file;
}
}
二.音频录制-MediaRecord
1.使用步骤
第1步:设置音频来源(MIC表示麦克风)
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
第2步:设置音频输出格式(默认的输出格式)
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
第3步:设置音频编码方式(默认的编码方式)
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
第4步:指定音频输出文件
mediaRecorder.setOutputFile(audioFile.getAbsolutePath());
第5步:调用prepare方法
mediaRecorder.prepare();
第6步:调用start方法开始录音
mediaRecorder.start();
第7步:调用stop方法停止录制
mediaRecorder.stop();
第8步:完成录制调用release方法释放资源
mediaRecorder.release();
2.所需权限
存储权限——如果应用程序要把图像或视频保存到设备的外部存储上(SD卡),并对文件进行操作和写入。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
录音权限——要用音频捕获来录音,应用程序必须请求音频捕获权限。
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
3.简单示例
写入权限
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
布局文件
<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.administrator.cameravideo.MainActivity2">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始录音"
android:onClick="recordClick"
android:id="@+id/button_record"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止"
android:onClick="stopClick"
android:id="@+id/button_stop"
android:layout_below="@+id/button_record"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignRight="@+id/button_record"
android:layout_alignEnd="@+id/button_record" />
</RelativeLayout>
MainActivity.java
import android.app.Activity;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import java.io.File;
import java.io.IOException;
public class MainActivity2 extends Activity implements MediaRecorder.OnErrorListener {
private MediaRecorder mr;
private boolean prepared = false;
private Button button_record;
private Button button_stop;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
button_record = (Button) findViewById(R.id.button_record);
button_stop = (Button) findViewById(R.id.button_stop);
mr = new MediaRecorder();
init();
}
private void init() {
mr.reset();
mr.setAudioSource(MediaRecorder.AudioSource.MIC);
mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) +
File.separator + System.currentTimeMillis()+ ".mp3";
mr.setOutputFile(path);
try {
mr.prepare();
prepared = true;
} catch (IOException e) {
e.printStackTrace();
}
button_stop.setEnabled(false);
}
public void recordClick(View view) {
if (prepared) {
mr.start();
prepared = false;
}
button_stop.setEnabled(true);
button_record.setEnabled(false);
}
public void stopClick(View view) {
mr.stop();
init();
button_stop.setEnabled(false);
button_record.setEnabled(true);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mr != null) {
mr.release();
}
}
@Override
public void onError(MediaRecorder mr, int what, int extra) {
mr.reset();
}
}
4.优缺点以及注意事项
- 优点
可以录制音频、视频
提供了录制、压缩、编码等功能
使用简单方便,几行代码就可实现 - 缺点
可以录制的视频格式较少
录制的过程中不能暂停
不能实时处理音频数据(实时对讲的话用它就不适合了) - 注意
模拟器不支持音频、视频录制,只能在真机上测试
录制一定打开录制权限 android.permission.RECORD_AUDIO
Android 9(API级别28)或更高,应用程序在后台运行不能访问麦克风
三.Vitamio框架
1.简介
Vitamio 是一款 Android 与 iOS 平台上的全能多媒体开发框架,全面支持硬件解码与 GPU 渲染。Vitamio 凭借其简洁易用的 API 接口赢得了全球众多开发者的青睐。到目前,全球已经有超过 一万 种应用在使用 Vitamio,覆盖用户超过 5亿 。
Vitamio 能够流畅播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常见格式的视频,还可以在 Android 与 iOS 上跨平台支持 MMS, RTSP, RTMP, HLS(m3u8) 等常见的多种视频流媒体协议,包括点播与直播。
Vitamio基于VPlayer开发,所以VPlayer能播放的Vitamio也能。
支持 Android 2.1+ 系统,支持超过 95% 的 Android 市场。同时 Android 2.1 之前的系统也基本支持,不过没做详细测试。
2.准备工作
下载Vitamio。在AS中添加依赖。必须加上以下权限和内容
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Don't forgot InitActivity -->
<activity
android:name="io.vov.vitamio.activity.InitActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
android:launchMode="singleTop"
android:theme="@android:style/Theme.NoTitleBar"
android:windowSoftInputMode="stateAlwaysHidden" />
在界面Avtivity设置布局前加上
Vitamio.isInitialized(getApplicationContext());
3.案例
1)播放音频
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.administrator.vitamio.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PLAY"
android:onClick="play"
android:id="@+id/button_play"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="pause"
android:onClick="pause"
android:id="@+id/button_pause"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/button_play"
android:layout_toStartOf="@+id/button_play" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop"
android:onClick="stop"
android:id="@+id/button_stop"
android:layout_alignBottom="@+id/button_play"
android:layout_toRightOf="@+id/button_play"
android:layout_toEndOf="@+id/button_play" />
</RelativeLayout>
MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import java.io.IOException;
import io.vov.vitamio.MediaPlayer;
import io.vov.vitamio.Vitamio;
public class MainActivity extends Activity implements MediaPlayer.OnPreparedListener {
private MediaPlayer mediaplayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载so类库(通常使用C。C++编写类库)
/*if (!LibsChecker.checkVitamioLibs(this))
{
return ;
}
*/
Vitamio.isInitialized(getApplicationContext());
setContentView(R.layout.activity_main);
initMethodPlayer();
}
private void initMethodPlayer() {
mediaplayer=new MediaPlayer(this);
}
public void play(View view)
{
String path= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)+"/a.mp3";
try {
mediaplayer.reset();
mediaplayer.setDataSource(path);
mediaplayer.setOnPreparedListener(this);
mediaplayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
public void pause(View view)
{
mediaplayer.pause();
}
public void stop(View view)
{
mediaplayer.stop();
mediaplayer.release();
}
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
}
2)VideoView播放视频
activity_main2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
tools:context="com.example.administrator.vitamio.MainActivity2">
<io.vov.vitamio.widget.VideoView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/surface_view"/>
</LinearLayout>
MainActivity2.java
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import io.vov.vitamio.Vitamio;
import io.vov.vitamio.widget.MediaController;
import io.vov.vitamio.widget.VideoView;
public class MainActivity2 extends AppCompatActivity {
private VideoView vv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Vitamio.isInitialized(getApplicationContext());
setContentView(R.layout.activity_main2);
if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this))
return;
vv= (VideoView) findViewById(R.id.surface_view);
MediaController mc=new MediaController(this);
vv.setMediaController(mc);
String path= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)+"/Nothing.ifox";
vv.setVideoPath(path);
vv.requestFocus();
vv.start();
}
}
注意事项
if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this))
return;
这句话是用来检测Vitamio是否解压解码包,一定要加