mediaplayerandroid
‘壹’ android的MediaPlayer支持哪些视频格式
Android官方公布的文档显示MediaPlayer支持如下视频格式:
Video H.263 X X 3GPP (.3gp) and MPEG-4 (.mp4)
H.264 AVC X 3GPP (.3gp) and MPEG-4 (.mp4)
MPEG-4 SP X 3GPP (.3gp)
这些格式的视频,基本上属于手机支持的视频格式。如果想观看其他类型格式的视频,比如flv等,需要下载暴风、迅雷等播放器。
‘贰’ androidmediaplayer默认是分段加载
这意味着它会从网络流中下载并缓冲较小的数据姿饥块,并迹冲返在接收到足够的数据后开始播放。当播放器缓冲区中的数据不足以支持连续播放时,它将尝试下载更多的数据。这种边下载判漏边播放的方式旨在提高播放的稳定性和流畅性,在网络条件不理想或者网络速度不够快的情况下,也能保证视频可以顺畅播放。不过也可能会导致初始加载时间稍长一些,因为需要先缓冲一段数据才能开始播放。
‘叁’ android MediaPlayer如何播放中文文件MP3
大概思路
1、在一个Activity类中,搞一个按钮,点击该按钮后,使用intent在后台启动一个service,。
2、写一个普通类extends Service,在这个service中进行Mp3文件的播放。
流程代码如下:
1、public class PlayerActivity extends Activity{
class StartButtonListener implements OnClickListener{
public void onClick( View v ){
/*----创建一个Intent对象,用于通知Service开始播放Mp3文件-----*/
Intent intent = new Intent();
intent.setClass( PlayerActivity.this, PlayerService.class );
intent.putExtra("mp3Info", mp3Info );
intent.putExtra("MSG", AppConstant.PlayerMsg.PLAY_MSG );
startService ( intent );//启动Service
}
}
}
2、public class PlayerService extends Service{
/**---获得从PlayerActivity传来的intent,启动PlayerService,并执行该方法 根据intent中包含的 指令,进行Mp3的播放---------------*/
public int onStartCommand(Intent intent, int flags, int startId) {
mp3Info = ( Mp3Info )intent.getSerializableExtra( "mp3Info" );
int MSG = intent.getIntExtra( "MSG", 0 );
if ( mp3Info != null ){
if( MSG == AppConstant.PlayerMsg.PLAY_MSG );{
play ( mp3Info );
}
}
else{
if ( MSG == AppConstant.PlayerMsg.PAUSE_MSG ){
pause( );
}
else if ( MSG == AppConstant.PlayerMsg.STOP_MSG ){
stop( );
}
}
return super.onStartCommand(intent, flags, startId );
}
private void play(Mp3Info mp3Info ){
if( !isPlaying ){
fileUtils = new FileUtils();
String path = fileUtils.getMp3Path ( mp3Info ); //获取Mp3文件在SDCard中的位置
mediaPlayer = MediaPlayer.create( this, Uri.parse("file://" + path) );//这里Uri.parse表示,获取SDCard中的文件,协议是file://
mediaPlayer.setLooping(false);
mediaPlayer.start(); //mediaPlayer在得到,Mp3文件在SDCard中的位置后,就可以进行播放了
}
}
}
‘肆’ 安卓 能用mediarecorder和mediaplayer实现即时语音吗
android语音录制可以通过MediaRecorder和AudioRecorder。
MediaRecorder本来是多媒体录制控件,可以同时录制视频和语音,当不指定视频源时就只录制语音;AudioRecorder只能录制语音。
二者录制的区别在于,MediaRecorder固定了语音的编码格式,具体平台支持类型可以在http://developer.android.com/guide/appendix/media-formats.html这里查看,而且使用时指定输出文件,在录制的同时系统将语音数据写入文件。AudioRecorder输出的是pcm,即原始音频数据,使用者需要自己读取这些数据,这样的好处是可以根据需要边录制边对音频数据处理,读取的同时也可以保存到文件进行存储。
语音的播放可以使用MediaPlayer和AudioTracker,与上面的对应,MediaPlayer可以播放各种多媒体文件,而AudioTracker只能播放pcm数据,使用者手动将数据连续写入进行播放。
MediaRecorder的使用
[java] view plain print?
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
AudioRecorder录制语音
[java] view plain print?
int suggestBufferSize = AudioRecord.getMinBufferSize(mSampleRate,
mChannelConfig, mAudioFormat);
mAudioRecord = new AudioRecord(AudioSource.MIC, mSampleRate,
mChannelConfig, mAudioFormat, suggestBufferSize);
mAudioRecorder.startRecording();
byte[] inByteBuf = new byte[BUF_SIZE]
while (runFlag) {
int readSize = mAudioRecord.read(inByteBuf, 0, inByteBuf.length);
}
mAudioRecorder.stop();
mAudioRecord.release();
上面是AudioRecorder的完整使用过程,AudioRecorder实例化的时候需要指定录音源、采样率等音频参数,最后一个是音频数据缓冲区大小,需要通过AudioRecord.getMinBufferSize()来得到缓冲区的最小值,如果实例化时参数小于这个最小值,那么AudioRecoder将创建失败。当然大于这个值肯定可以。之后通过read将缓冲区的数据读出来。
之前一直以为读取时使用的byte数组大小必须和缓冲区的大小一致,但实际并不是这样,看下AudioRecorder构造函数中对bufferSizeInBytes的解释:
bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written to ring the recording. New audio data can be read from this buffer in smaller chunks than this size.
也就是说缓冲区只是系统用来临时存放音频数据的,读取时可以每次读取较小的块,然后多次读取。
AudioRecorder还有一个方法setPositionNotificationPeriod (int periodInFrames)。这个方法可以在读取指定数据后发出一个回调,需要配合 (AudioRecord. listener),当读取的总数据是指定的periodInFrames的整数倍时就会调用listner的方法onPeriodicNotification.
[java] view plain print?
new () {
@Override
public void onPeriodicNotification(AudioRecord recorder) {
// TODO Auto-generated method stub
}
@Override
public void onMarkerReached(AudioRecord recorder) {
// TODO Auto-generated method stub
}
};
这个特性使用时有个注意点,就是回调只会发生在实际数据读取之后,也就是使用者通过read方法读取出periodInFrames这么多数据时才会触发这个回调,否则什么也不会发生。
MeidaPlayer播放音频文件
[java] view plain print?
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();
mediaPlayer.stop();
mediaPlayer.release();
其中setDataSource()有多个覆写,如下
void setDataSource(String path)
Sets the data source (file-path or http/rtsp URL) to use.
void setDataSource(Context context, Uri uri, Map<String, String> headers)
Sets the data source as a content Uri.
void setDataSource(Context context, Uri uri)
Sets the data source as a content Uri.
void setDataSource(FileDescriptor fd, long offset, long length)
Sets the data source (FileDescriptor) to use.
void setDataSource(FileDescriptor fd)
Sets the data source (FileDescriptor) to use.
可以看到不同的输入参数指定了数据的来源。其中setDataSource(FileDescriptor fd, long offset, long length)可以指定开始读取的偏移量和长度。
之所以会注意到这个参数是因为在实际使用时有一个需求,即可以播放WAV文件,又可以播放MP3文件,而且能够限定播放开始和结束的位置。
对于MP3文件使用setDataSource(FileDescriptor fd, long offset, long length)是完全可行的,像这样
[java] view plain print?
mPlayer.reset();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(
new FileInputStream(mSoundFile.getFilePath()).getFD(),
startByte, endByte - startByte);
[java] view plain print?
mPlayer.prepare();
但WAV文件却完全没有效果,是什么原因呢,看下官方对setDataSource(FileDescriptor fd, long offset, long length)的解释
Sets the data source (FileDescriptor) to use. The FileDescriptor must be seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility to close the file descriptor. It is safe to do so as soon as this call returns.
注意到该方法指定的文件类型必须是seekable的,mp3文件属于这种类型(tips:不知道还有没有其他类型),因为mp3内部是按帧存储的,可以指定到具体的帧位置,而WAV文件音频数据是pcm,也就是一大片完整的数据,要对wav文件指定开始播放位置,需要使用另一个方法seekTo (int msec)。这里指定的参数是毫秒。
开始时间可以指定了,那结束播放的时间如何指定?
MediaPlayer有另外两个方法:getDuration ()和getCurrentPosition (),这两个返回的都是时间信息,前者返回总的播放时间,后者返回当前播放位置的时间。
那返回的结果对于mp3和wav是否会不同呢?会!
对WAV类型,getDuration返回的是音频文件的总时间,getCurrentPosition返回的是从文件起始到现在的播放时间;而对mp3类型,getDuration返回的是startByte和endByte之间播放的时间间隔,getCurrentPosition返回从startByte到现在的播放时间。想一下原因也可以明白,因为MP3是可以精确指定起始位置的,所以所有计算都可以从指定的位置开始,而wav文件一切只能从最开始的位置计算。
‘伍’ android 怎样获得mediaplayer播放的音频数据
Android中音频和视频的播放我们最先想到的就是MediaPlayer类了,该类提供了播放、暂停、停止、和重复播放等方法。该类位于android.media包下,详见API文档。其实除了这个类还有一个音乐播放类那就是SoundPool,这两个类各有不同分析一下便于大家理解
MediaPlayer:
此类适合播放较大文件,此类文件应该存储在SD卡上,而不是在资源文件里,还有此类每次只能播放一个音频文件。
此类用法如下:
1、从资源文件中播放
MediaPlayer player = new MediaPlayer.create(this,R.raw.test);
player.stare();
2、从文件系统播放
MediaPlayer player = new MediaPlayer();
String path = "/sdcard/test.mp3";
player.setDataSource(path);
player.prepare();
player.start();
3、从网络播放
(1)通过URI的方式:
String path="http://**************.mp3"; //这里给一个歌曲的网络地址就行了
Uri uri = Uri.parse(path);
MediaPlayer player = new MediaPlayer.create(this,uri);
player.start();
(2)通过设置数据源的方式:
MediaPlayer player = new MediaPlayer.create();
String path="http://**************.mp3"; //这里给一个歌曲的网络地址就行了
player.setDataSource(path);
player.prepare();
player.start();
SoundPool:
此类特点就是低延迟播放,适合播放实时音实现同时播放多个声音,如游戏中炸弹的爆炸音等小资源文件,此类音频比较适合放到资源文件夹 res/raw下和程序一起打成APK文件。
用法如下:
SoundPool soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
HashMap<Integer, Integer> soundPoolMap = new HashMap<Integer, Integer>();
soundPoolMap.put(1, soundPool.load(this, R.raw.dingdong1, 1));
soundPoolMap.put(2, soundPool.load(this, R.raw.dingdong2, 2));
public void playSound(int sound, int loop) {
AudioManager mgr = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float volume = streamVolumeCurrent/streamVolumeMax;
soundPool.play(soundPoolMap.get(sound), volume, volume, 1, loop, 1f);
//参数:1、Map中取值 2、当前音量 3、最大音量 4、优先级 5、重播次数 6、播放速度
}
this.playSound(1, 0);
‘陆’ android中如何判断mediaplayer已经停止
1、release是当MediaPlayer对象(以下简称mp)不再使用才去释放mp所占有的资源。不是一首歌完了之后要用的,而是你不再使用mp之后才调用,比如退出。
2、start和stop之间循环的流程应该是:reset()-->setDataSource(path)-->prepare()-->start()-->stop()--reset()-->重来上述流程一遍。
3、判断停止是要用到
MediaPlayer.OnCompletionListener
mCompleteListener的方法监听。
你对mediaplayer整个流程的理解有点混乱,建议多看代码吧。
‘柒’ 如何单元测试android mediaplayer
主要涉及类:MediaPlayer
(1) 当一个MediaPlayer对象被创建或者调用reset()方法之后,它处于空闲状态,调用release()方法后处于结束状态
1,一个MediaPlayer对象调用了reset()方法后,再调用其它方法可能会触发OnErrorListener.onError()事件,未调用reset()方法则不会触发
2,当Mediaplayer对象不再被使用时,最好调用release()方法对其进行释放,使其处于结束状态,此时它不能被使用
3,Mediaplayer对象被创建时(调用构造方法)处于空闲状态,若使用create()方法创建后则处于准备状态。
(2) 一般情况下,一些常用的播放控制操作可能因为音频、视频的格式不被支持或者质量较差以及流超时,也有可能由于开发者的疏忽使得Mediaplayer对象处于无效状态等而导致错误。此时可通过注册setOnErrorListener方法实现监控。如果发生了错误,Mediaplayer对象将处于多雾状态,可以使用reset()方法来回复错误。
(3) 任何Mediaplayer对象都必须先处于准备状态,然后才开始播放
(4) 要开始播放Mediaplayer对象都必须成功调用start()方法,可通过isPlaying()方法来检测是否正在播放
(5) 当Mediaplayer对象在播放时,可以进行暂停和停止操作,pause()方法暂停播放,stop()方法停止播放。处于暂停暂停时可通过start()方法恢复播放,但是处于停止状态时则必须先调用prepare()方法使其处于准备状态,再调用start()方法。
主要方法:
Mediaplayer:构造方法
create: 创建一个要播放的多媒体
getCurrentPosition:得到当前播放位置
getDuration: 得到文件的时间
prepare: 准备(同步)
prepareAsync:准备(异步)
seekTo: 指定播放的位置(以毫秒为单位)
setAudioStreamType: 设置流媒体的类型
setDataSource: 设置数据来源
setDisplay: 设置用SurfaceHolder来显示多媒体
setOnBufferingUpdateListener: 网络流媒体的缓冲监听
setOnErrorListener: 设置错误信息监听
setOnVideoSizeChangedListener:视频尺寸监听
setScreenOnWhilePlaying: 设置是否使用SurfaceHolder来显示
setVolume: 设置音量
//获取sd卡上的音频文件
setDataSource(“/sdcard/test.mp3”);
//装载资源中的音乐
MediaPlayer.create(Activity01.this,R.raw.test);
//目前存在问题,不能循环解析出音频文件
原因:.android_secure文件夹受保护,无法获取里面的文件信息
播放视频
相关类:VideoView
方法说明:
getBufferPercentage:得到缓冲的百分比
getCurrentPosition:得到当前播放位置
getDuration:得到视频文件的时间
resolveAdjustedSize:调整视频显示大小
setMediaController:设置播放控制器模式(播放进度条)
setOnCompletionListener:当视频文件播放完时触发事件
setVideoPath:设置视频源路径
setVideoURI:设置视频源地址
录音
相关类:MediaRecorder
方法说明:
MediaRecorder:构造方法
getMaxAmplitude:得到最大幅度
setAudioEncoder:设置音频编码
setAudioSource:设置音频源
setCamera:设置摄像机
setMaxDuration:设置最长录音时间
setMaxFileSize:设置文件的最大尺寸
setOutputFile:设置输出文件
setOutputFormat:设置输出文件格式
setPreviewDisplay:设置预览
setVideoEncoder:设置视频编码
setVideoFrameRate:设置视频帧的频率
setVideoSize:设置视频的宽度和高度(分辨率)
setVideoSource:设置视频源
File类下的方法:
public static File createTempFile(String prefix, String suffix, File directory)
Creates an empty temporary file in the given directory using the given prefix and suffix as part of the file name.
系统会自动在prefix和suffix之间加上一些数字来构建完整的文件名
实现录音的一般步骤:
1, 实例化MediaRecorder mr,调用构造方法
2, 初始化mr:mr.setAudioSource(MIC)/setVideoSource(CAMERA)
3, 配置DataSource:设置输出文件格式/路径,编码器等
4, 准备录制:mr.prepare()
5, 开始录制:mr.start()
6, 停止录制:mr.stop()
7, 释放资源:mr.release()
注:2,3不可调换顺序
添加许可:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO">
相机设置
相关类:Camera,它是专门用来连接和断开相机服务的类
Camera的几个事件:
Camera.AutoFocusCallback: 自动调焦功能
Camera.ErrorCallback: 错误信息捕捉
Camera.Parameters: 相机的属性参数
Camera.PictureCallback: 拍照、产生图片时触发
Camera.PreviewCallback: 相机预览设置
Camera.ShutterCallback: 快门设置
Camera.Size: 图片的尺寸
Camera类没有构造方法,可通过open()方法来打开相机设备
Camera类的方法介绍:
autoFocus: 设置自动对焦
getParameters: 得到相机参数
open: 启动相机服务
release: 释放相机服务
setParameters: 设置参数
setPreviewDisplay:设置预览
startPreview: 开始预览
stopPreview: 停止预览
takePicture: 拍照
注:takePicture方法要实现3个回调函数作为它的三个参数:Camera.ShutterCallback(快门),和两个Camera.Picture.Callback(图像数据)。
需要许可
<uses-permission android:name="android.permission.CAMERA" />
若要将图片存储至sd卡中,则需要sd卡读写许可
目前存在问题:只能拍照一次,不能重新回到预览界面
闹钟设置
相关类:AlarmManager,它是专门用来设定在某个指定的时间去完成指定的事件。AlarmManager提供了访问系统警报的服务,只要在程序中设置了警报服务,AlarmManager就会通过onReceive()方法去执行这些事件,就算系统处于待机状态,同样不会影响运行。可通过Context.getSystemService(ALARM_SERVICE)方法来获得该服务。
方法说明:
cancel: 取消AlarmManager服务
set: 设置AlarmManager服务
setInexactRepeating:设置不精确周期
setRepeating:设置精确周期
setTimeZone:设置时区
注:需创建一个BroadcastReceiver的子类,并覆盖onReceive()方法
铃声设置
系统自带的铃声都放在/system/medio/audio/文件夹中
铃音类型: TYPE_RINGTONE(来电铃音),TYPE_ALARM,TYPE_NOTIFICATION
相关类:RingtoneManager
方法介绍:
getActualDefaultRingtoneUri:取得指定类型的铃声
getCursor:返回所有可用铃声的游标
getDefaultType:得到指定URI默认的铃声类型
getRingtone
getRingtonePosition:得到铃声位置
getRingtoneUri
getValidRingtoneUri:得到一个可用铃声的URI
isDefault:得到指定的Uri是否为默认的铃声
setActualDefaultRingtoneUri:设置默认的铃声
获取的Cursor共有4列,列名依次为:_id,title,”content://media/internal/audio/media”,title_key
以设置手机铃音为例:
if (isFolder(strRingtongFolder)) {//如果不存在该文件夹则创建一个
// 打开系统铃声设置
Intent intent = new Intent(
RingtoneManager.ACTION_RINGTONE_PICKER);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, true);
// 类型为来电ringtong
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE,
RingtoneManager.TYPE_RINGTONE);
// 设置显示的题目
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "设置来电的铃声");
// 当设置完成之后返回到当前的activity
startActivityForResult(intent, RingtongButton);
}
然后复写onActivityResult(int requestCode, int resultCode, Intent data)方法,resultCode就是点击设置dialog的按钮编号,需要判断是否点击了确认按钮
if (resultCode != RESULT_OK) {
return;
}
try {
// 得到我们选择的铃声
Uri pickedUri = data .getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
// 将我们选择的铃声选择成默认
if (pickedUri != null) {
RingtoneManager.setActualDefaultRingtoneUri(
Media_RingTongActivity.this,
RingtoneManager.TYPE_RINGTONE, pickedUri);
}
} catch (Exception e) {
e.printStackTrace();
}