【移动应用开发技术】怎么在Android中使用MediaRecorder类实现视频和音频录制功能_第1页
【移动应用开发技术】怎么在Android中使用MediaRecorder类实现视频和音频录制功能_第2页
【移动应用开发技术】怎么在Android中使用MediaRecorder类实现视频和音频录制功能_第3页
【移动应用开发技术】怎么在Android中使用MediaRecorder类实现视频和音频录制功能_第4页
【移动应用开发技术】怎么在Android中使用MediaRecorder类实现视频和音频录制功能_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】怎么在Android中使用MediaRecorder类实现视频和音频录制功能

怎么在Android中使用MediaRecorder类实现视频和音频录制功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、前期基础知识储备Android提供了MediaRecorder这一个类来实现视频和音频的录制。

由官方配图可知,MediaRecorder用于录制视频时需要调用一系列的API来设置和录制相关的配置,而且调用方法的顺序是固定的,必须按照这个顺序进行API调用才能正确利用手机摄像头实现录像功能。调用MediaRecorder的录像API顺序如下:1)OpenCamera-UsetheCamera.open()togetaninstanceofthecameraobject.

2)ConnectPreview-PreparealivecameraimagepreviewbyconnectingaSurfaceViewtothecamerausingCamera.setPreviewDisplay().

3)StartPreview-CallCamera.startPreview()tobegindisplayingthelivecameraimages.

4)StartRecordingVideo-Thefollowingstepsmustbecompletedinordertosuccessfullyrecordvideo:

a.UnlocktheCamera-UnlockthecameraforusebyMediaRecorderbycallingCamera.unlock().

b.ConfigureMediaRecorder-CallinthefollowingMediaRecordermethodsinthisorder:setCamera()-Setthecameratobeusedforvideocapture,绑定Camera进行视频录制。setAudioSource()-Settheaudiosource,设置音频源。setVideoSource()-Setthevideosource,设置视频源。setProfile()-Setthevideooutputformatandencoding,录制效果的配置。setOutputFile()-Settheoutputfile,设置录制好的文件存储位置。setPreviewDisplay()-ConnectPreview,设置预览效果。c.PrepareMediaRecorder-PreparetheMediaRecorderwithprovidedconfigurationsettingsbycallingMediaRecorder.prepare().

d.StartMediaRecorder-StartrecordingvideobycallingMediaRecorder.start().停止录像时调用的API顺序如下:1)StopMediaRecorder-StoprecordingvideobycallingMediaRecorder.stop().

2)ResetMediaRecorder-Optionally,removetheconfigurationsettingsfromtherecorderbycallingMediaRecorder.reset().

3)ReleaseMediaRecorder-ReleasetheMediaRecorderbycallingMediaRecorder.release().

4)LocktheCamera-LockthecamerasothatfutureMediaRecordersessionscanuseitbycallingCamera.lock().

5)StopthePreview-Whenyouractivityhasfinishedusingthecamera,stopthepreviewusingCamera.stopPreview().

6)ReleaseCamera-ReleasethecamerasothatotherapplicationscanuseitbycallingCamera.release().二、上代码,具体实现录制视频和视频播放功能这里调用MediaRecorder的API实现视频录制功能并借用MediaPlayer多媒体播放类实现录制好的视频播放。(1)布局文件如下,非常简单两个按钮下放置一个SurfaceView;<LinearLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

<LinearLayout

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

<Button

android:id="@+id/record_btn"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="15dp"

android:layout_weight="1"

android:text="record"

/>

<Button

android:id="@+id/play_btn"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginRight="15dp"

android:layout_weight="1"

android:text="play"

/>

</LinearLayout>

<SurfaceView

android:id="@+id/surface_view"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_marginBottom="20dp"

/>

</LinearLayout>(2)相机录像前的准备代码;

/*

*

相机预览前的准备工作代码

单独抽出来

*

*/

private

boolean

prepareVideoRecorder()

throws

IOException

{

if

(mMediaRecorder

==

null)

{

mMediaRecorder

=

new

MediaRecorder();

mMediaRecorder.reset();

}

/*camera相关设置部分*/

mCamera

=

Camera.open(0);//Camera.CameraInfo.CAMERA_FACING_BACK

if

(mCamera

!=

null)

{

//设置旋转角度,顺时针方向,因为默认是逆向90度的,这样图像就是正常显示了

mCamera.setDisplayOrientation(90);

mCamera.unlock();

mMediaRecorder.setCamera(mCamera);

}

/*recorder设置部分*/

mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);

mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

mMediaRecorder.setOutputFile(getOutputMediaFile());

mMediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());

mMediaRecorder.prepare();

return

true;

}(3)创建录像文件存储位置代码;

/*

*

获取手机外部存储路径

*

*/

private

String

getOutputFile()

{

File

mediaFile

=

null;

boolean

OutputExist

=

Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);

if

(OutputExist)

{

mediaFile

=

Environment.getExternalStorageDirectory();

return

mediaFile.toString();

}

return

null;

}

/*

*

获取录制视频的日期

作为存储文件路径一部分

*

*/

private

String

getDate()

{

Log.d(TAG,

"获取录制视频的日期

");

Calendar

ca

=

Calendar.getInstance();

int

year

=

ca.get(Calendar.YEAR);

//

获取年份

int

month

=

ca.get(Calendar.MONTH);

//

获取月份

int

day

=

ca.get(Calendar.DATE);

//

获取日

String

date

=

""

+

year

+

"_"

+

(month

+

1)

+

"_"

+

day;

return

date;

}

/*

*创建视频存储文件夹

录制好的视频存储在手机外部存储中

以录像时间+mp4格式命名

*

*/

private

String

getOutputMediaFile()

{

Log.d(TAG,

"获取视频存储的位置

");

String

mediaPath

=

getOutputFile();

if

(mediaPath

!=

null)

{

File

mediaFile

=

new

File(mediaPath

+

"/recordVideo");

if

(!mediaFile.exists())

{

mediaFile.mkdir();

}

return

mMediaPath

=

mediaFile.getAbsolutePath()

+

File.separator

+

getDate()

+

".mp4";

}

return

null;

}(4)录制视频结束时释放相机资源;

/*

*

录制视频结束时释放相机资源

*

*/

private

void

releaseMediaRecorder()

{

Log.d(TAG,

"录制结束后释放资源

");

if

(mMediaRecorder

!=

null)

{

mMediaRecorder.reset();

//

clear

recorder

configuration

mMediaRecorder.release();

//

release

the

recorder

object

mMediaRecorder

=

null;

mCamera.lock();

//

lock

camera

for

later

use

}

}(5)点击录制视频按钮mRecordBtn开始录制和再次点击停止录制;

private

void

initBtnClick()

{

StartRecording();

mPlayBtn.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

view)

{

if

(mMediaPlayer

==

null)

{

mMediaPlayer

=

new

MediaPlayer();

mMediaPlayer.reset();

Uri

uri

=

Uri.parse(mMediaPath);

mMediaPlayer

=

MediaPlayer.create(MainActivity.this,uri);

mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

mMediaPlayer.setDisplay(mSurfaceHolder);

try{

mMediaPlayer.prepare();

}catch

(Exception

e){

e.printStackTrace();

}

mMediaPlayer.start();

}

}

});

}

private

void

StartRecording(){

mRecordBtn.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

view)

{

if

(!mIsRecord)

{

try

{

Log.d(TAG,

"首次点击开始录像

");

if

(prepareVideoRecorder())

{

mMediaRecorder.start();

mIsRecord

=

true;

mRecordBtn.setText("stop");

}

}

catch

(IOException

e)

{

e.printStackTrace();

}

}

else

{

Log.d(TAG,

"再次点击停止录像");

mMediaRecorder.stop();

releaseMediaRecorder();

mCamera.lock();

mRecordBtn.setText("record");

mIsRecord

=

false;

if

(mCamera

!=

null)

{

mCamera.release();

mCamera

=

null;

}

}

}

});

}(6)点击播放视频按钮mPlayBtn开始播放录制刚刚录制好的视频;

mPlayBtn.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

view)

{

if

(mMediaPlayer

==

null)

{

mMediaPlayer

=

new

MediaPlayer();

mMediaPlayer.reset();

Uri

uri

=

Uri.parse(mMediaPath);

mMediaPlayer

=

MediaPlayer.create(MainActivity.this,uri);

mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

mMediaPlayer.setDisplay(mSurfaceHolder);

try{

mMediaPlayer.prepare();

}catch

(Exception

e){

e.printStackTrace();

}

mMediaPlayer.start();

}

}

});(7)针对6.0以上系统进行运行时权限申请

private

void

requestCameraAndStoragePermission()

{

//检查用户是否授权

for

(int

i

=

0;

i

<

permissions.length;

i++)

{

if

(ContextCompat.checkSelfPermission(MainActivity.this,

permissions[i])

!=

PackageManager.PERMISSION_GRANTED)

{

//没有授权则请求相应权限

ActivityCompat.requestPermissions(MainActivity.this,

new

String[]{permissions[i]},

1);

}

}

//利用权限申请工具类来实现

mPermissionsUtils

=

PermissionsUtils.getInstance();

mPermissionsUtils.chekPermissions(MainActivity.this,permissions,

permissionsResult);

}

//创建监听权限的接口对象

PermissionsUtils.IPermissionsResult

permissionsResult

=

new

PermissionsUtils.IPermissionsResult()

{

@Override

public

void

passPermissons()

{

//StartRecording();

注意这里的逻辑

并不是权限通过了就立即开始录像了

而是权限通过了

就可以打开Camera进行预览

mCamera

=

Camera.open(0);//Camera.CameraInfo.CAMERA_FACING_BACK

}

@Override

public

void

forbitPermissons()

{

Toast.makeText(MainActivity.this,

"You

denyied

the

permission",

Toast.LENGTH_SHORT).show();

}

};录制视频及播放录制视频完整代码如下public

class

MainActivity

extends

AppCompatActivity

implements

SurfaceHolder.Callback{

private

static

final

String

TAG

=

"MainActivity";

private

SurfaceView

mSurfaceView;

private

Button

mRecordBtn,

mPlayBtn;

private

boolean

mIsRecord

=

false;

//是否正在录像

private

Camera

mCamera;

private

MediaRecorder

mMediaRecorder;

private

String

mMediaPath;

private

MediaPlayer

mMediaPlayer;

private

SurfaceHolder

mSurfaceHolder;

private

PermissionsUtils

mPermissionsUtils;

private

String[]

permissions

=

{Manifest.permission.WRITE_EXTERNAL_STORAGE,

Manifest.permission.CAMERA,

Manifest.permission.RECORD_AUDIO};

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//6.0及以上系统请求运行时权限

利用权限申请工具类(见下文)

requestCameraAndStoragePermission();

mSurfaceView

=

(SurfaceView)

findViewById(R.id.surface_view);

mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

//

必须-设置Surface不需要维护自己的缓冲区

mRecordBtn

=

(Button)

findViewById(R.id.record_btn);

mPlayBtn

=

(Button)

findViewById(R.id.play_btn);

initBtnClick();

SurfaceHolder

holder

=

mSurfaceView.getHolder();

holder.addCallback(this);

}

private

void

requestCameraAndStoragePermission()

{

//检查用户是否授权

for

(int

i

=

0;

i

<

permissions.length;

i++)

{

if

(ContextCompat.checkSelfPermission(MainActivity.this,

permissions[i])

!=

PackageManager.PERMISSION_GRANTED)

{

//没有授权则请求相应权限

ActivityCompat.requestPermissions(MainActivity.this,

new

String[]{permissions[i]},

1);

}

}

//利用权限申请工具类来实现

mPermissionsUtils

=

PermissionsUtils.getInstance();

mPermissionsUtils.chekPermissions(MainActivity.this,permissions,

permissionsResult);

}

//创建监听权限的接口对象

PermissionsUtils.IPermissionsResult

permissionsResult

=

new

PermissionsUtils.IPermissionsResult()

{

@Override

public

void

passPermissons()

{

//

StartRecording();

注意这里的逻辑

并不是权限通过了就立即开始录像了

而是权限通过了

就可以打开Camera进行预览

mCamera

=

Camera.open(0);//Camera.CameraInfo.CAMERA_FACING_BACK

}

@Override

public

void

forbitPermissons()

{

Toast.makeText(MainActivity.this,

"You

denyied

the

permission",

Toast.LENGTH_SHORT).show();

}

};

private

void

StartRecording(){

mRecordBtn.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

view)

{

if

(!mIsRecord)

{

try

{

Log.d(TAG,

"首次点击开始录像

");

if

(prepareVideoRecorder())

{

mMediaRecorder.start();

mIsRecord

=

true;

mRecordBtn.setText("stop");

}

}

catch

(IOException

e)

{

e.printStackTrace();

}

}

else

{

Log.d(TAG,

"再次点击停止录像");

mMediaRecorder.stop();

releaseMediaRecorder();

mCamera.lock();

mRecordBtn.setText("record");

mIsRecord

=

false;

if

(mCamera

!=

null)

{

mCamera.release();

mCamera

=

null;

}

}

}

});

}

private

void

initBtnClick()

{

StartRecording();

mPlayBtn.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

view)

{

if

(mMediaPlayer

==

null)

{

mMediaPlayer

=

new

MediaPlayer();

mMediaPlayer.reset();

Uri

uri

=

Uri.parse(mMediaPath);

mMediaPlayer

=

MediaPlayer.create(MainActivity.this,uri);

mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

mMediaPlayer.setDisplay(mSurfaceHolder);

try{

mMediaPlayer.prepare();

}catch

(Exception

e){

e.printStackTrace();

}

mMediaPlayer.start();

}

}

});

}

/*

*

相机预览前的准备工作代码

单独抽出来

*

*/

private

boolean

prepareVideoRecorder()

throws

IOException

{

if

(mMediaRecorder

==

null)

{

mMediaRecorder

=

new

MediaRecorder();

mMediaRecorder.reset();

}

/*camera相关设置部分*/

mCamera

=

Camera.open(0);//Camera.CameraInfo.CAMERA_FACING_BACK

if

(mCamera

!=

null)

{

//设置旋转角度,顺时针方向,因为默认是逆向90度的,这样图像就是正常显示了

mCamera.setDisplayOrientation(90);

mCamera.unlock();

mMediaRecorder.setCamera(mCamera);

}

/*recorder设置部分*/

mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);

mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

mMediaRecorder.setOutputFile(getOutputMediaFile());

mMediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());

mMediaRecorder.prepare();

return

true;

}

/*

*

获取手机外部存储路径

*

*/

private

String

getOutputFile()

{

File

mediaFile

=

null;

boolean

OutputExist

=

Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);

if

(OutputExist)

{

mediaFile

=

Environment.getExternalStorageDirectory();

return

mediaFile.toString();

}

return

null;

}

/*

*

获取录制视频的日期

作为存储文件路径一部分

*

*/

private

String

getDate()

{

Log.d(TAG,

"获取录制视频的日期

");

Calendar

ca

=

Calendar.getInstance();

int

year

=

ca.get(Calendar.YEAR);

//

获取年份

int

month

=

ca.get(Calendar.MONTH);

//

获取月份

int

day

=

ca.get(Calendar.DATE);

//

获取日

String

date

=

""

+

year

+

"_"

+

(month

+

1)

+

"_"

+

day;

return

date;

}

/*

*创建视频存储文件夹

录制好的视频存储在手机外部存储中

以录像时间+mp4格式命名

*

*/

private

String

getOutputMediaFile()

{

Log.d(TAG,

"获取视频存储的位置

");

String

mediaPath

=

getOutputFile();

if

(mediaPath

!=

null)

{

File

mediaFile

=

new

File(mediaPath

+

"/recordVideo");

if

(!mediaFile.exists())

{

mediaFile.mkdir();

}

return

mMediaPath

=

mediaFile.getAbsolutePath()

+

File.separator

+

getDate()

+

".mp4";

}

return

null;

}

/*

*

录制视频结束时释放相机资源

*

*/

private

void

releaseMediaRecorder()

{

Log.d(TAG,

"录制结束后释放资源

");

if

(mMediaRecorder

!=

null)

{

mMediaRecorder.reset();

//

clear

recorder

configuration

mMediaRecorder.release();

//

release

the

recorder

object

mMediaRecorder

=

null;

mCamera.lock();

//

lock

camera

for

later

use

}

}

@Override

public

void

surfaceCreated(SurfaceHolder

surfaceHolder)

{

mSurfaceHolder

=

surfaceHolder;

}

@Override

public

void

surfaceChanged(SurfaceHolder

surfaceHolder,

int

i,

int

i1,

int

i2)

{

mSurfaceHolder

=

surfaceHolder;

}

@Override

public

void

surfaceDestroyed(SurfaceHolder

surfaceHolder)

{

mSurfaceView

=

null;

mSurfaceHolder

=

null;

releaseMediaRecorder();

if

(mCamera

!=

null)

{

mCamera.release();

mCamera

=

null;

}

if

(mMediaPlayer

!=

null){

mMediaPlayer.release();

mMediaPlayer

=

null;

}

}

}三、延伸知识,运行时权限申请工具类完整代码如下/**

*

运行时权限申请工具类:

*

检查用户是否授权——ContextCompat.checkSelfPermission

*

如果没有授权,那么申请授权——ActivityCompat.requestPermissions

*

申请授权之后的回调——onRequestPermissionsResult

*

精髓:检查权限

申请权限的代码写在工具类内

同时写入一个接口

两个抽象方法-获取权限成功

+

获取权限失败

然后在外部使用权限工具类时实现这两个抽象方法

*

Created

by

Administrator

on

2018/7/3.

*/

public

class

PermissionsUtils

{

private

final

int

mRequestCode

=

100;//权限请求码

public

static

boolean

showSystemSetting

=

true;

private

PermissionsUtils()

{

}

private

static

PermissionsUtils

permissionsUtils;

private

IPermissionsResult

mPermissionsResult;

/*

*

单例模式创建PermissionUtils实例

工具类中的静态方法可以直接使用类名+方法名调用

非静态方法还是需要获取到工具类的实例

实例对方法进行调用

*

*/

public

static

PermissionsUtils

getInstance()

{

if

(permissionsUtils

==

null)

{

synchronized

(PermissionsUtils.class)

{

if

(permissionsUtils

==

null)

permissionsUtils

=

new

PermissionsUtils();

}

}

return

permissionsUtils;

}

/*

*

检查用户是否授权

+

如果没有授权

则申请授权

-

系统标准方法

*

*/

public

void

chekPermissions(Activity

context,

String[]

permissions,

@NonNull

IPermissionsResult

permissionsResult)

{

mPermissionsResult

=

permissionsResult;

if

(Build.VERSION.SDK_INT

<

23)

{//6.0系统及以上才会动态申请权限

以下不用

所以直接return出去

permissionsResult.passPermissons();

return;

}

//创建一个mPermissionList,逐个判断哪些权限未授予,未授予的权限存储到mPerrrmissionList中

List<String>

mPermissionList

=

new

ArrayList<>();

//逐个判断你要的权限是否已经通过

for

(int

i

=

0;

i

<

permissions.length;

i++)

{

if

(ContextCompat.checkSelfPermission(context,

permissions[i])

!=

PackageManager.PERMISSION_GRANTED)

{

mPermissionList.add(permissions[i]);//添加还未授予的权限

}

}

//申请权限

if

(mPermissionList.size()

>

0)

{//有权限没有通过,需要申请

ActivityCompat.requestPermissions(context,

permissions,

mRequestCode);

}

else

{

//说明权限都已经通过,利用接口变量调用实现的接口方法

即有权限之后需要调用的方法

permissionsResult.passPermissons();

return;

}

}

//请求权限后回调的方法

//参数:

requestCode

是我们自己定义的权限请求码

//参数:

permissions

是我们请求的权限名称数组

//参数:

grantResults

是我们在弹出页面后是否允许权限的标识数组,数组的长度对应的是权限名称数组的长度,数组的数据0表示允许权限,-1表示我们点击了禁止权限

public

void

onRequestPermissionsResult(Activity

context,

int

requestCode,

@NonNull

String[]

permissions,

@NonNul

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论