Android基础11多媒体传感器.docx
《Android基础11多媒体传感器.docx》由会员分享,可在线阅读,更多相关《Android基础11多媒体传感器.docx(32页珍藏版)》请在冰豆网上搜索。
![Android基础11多媒体传感器.docx](https://file1.bdocx.com/fileroot1/2023-3/19/122fddc1-79ed-4d89-a9c0-35ce96bfeb58/122fddc1-79ed-4d89-a9c0-35ce96bfeb581.gif)
Android基础11多媒体传感器
Android课程同步笔记
Alpha0.01版
By阳哥
Android-多媒体&传感器
1.音频播放(★★)
1.1MediaPlayer
MediaPlayer播放器状态流程如下图:
该播放器同时只能播放一个音乐文件,文件大小并没有限制。
:
MediaPlayer必须严格按照状态图操作,否则就会出现错误,这些错误都是底层抛出,严格按照状态图操作的话一般就不会出问题。
使用MediaPlayer播放音乐的步骤
MediaPlayerplayer=newMediaPlayer();创建对象
player.reset();重置为初始状态
player.setAudioStreamType(AudioManager.STREAM_MUSIC);声音流类型
player.setDataSource(“/mnt/sdcard/test.mp3”);设置音频源
player.prepare();准备
player.start();开始或恢复播放
player.pause();暂停播放
player.start();恢复播放
player.stop();停止播放
player.release();
1.2SoundPool
SoundPool和其他声音播放类相比,其特点是可以自行设置声音的品质、音量、播放比率等参数。
并且它可以同时管理多个音频流,每个流都有独自的ID,对某个音频流的管理都是通过ID进行的。
1. SoundPool最大只能申请1M的内存空间,这就意味着我们只能用一些很短的声音片段,而不是用它来播放歌曲或者做游戏背景音乐。
2. SoundPool提供了pause和stop方法,但这些方法建议最好不要轻易使用,因为有些时候它们可能会使你的程序莫名其妙的终止。
有些朋友反映它们不会立即中止播放声音,而是把缓冲区里的数据播放完才会停下来,也许会多播放一秒钟。
3. SoundPool的效率问题。
其实SoundPool的效率在这些播放类中算是很好的了,这可能会影响用户体验。
也许这不能管SoundPool本身,因为到了性能比较好的Droid中这个延迟就可以让人接受了。
使用SoundPool播放音乐的步骤
创建SoundPool实例,第一个参数用于指定最大可以加载声音个数
SoundPoolsoundPool=newSoundPool(3,AudioManager.STREAM_MUSIC,0);
加载不同的声音文件,生成各自的声音id
intshoot1ID=soundPool.load(this,R.raw.shoot1,1);
intshoot2ID=soundPool.load(this,R.raw.shoot2,1);
intshoot3ID=soundPool.load(this,R.raw.shoot3,1);
根据load方法获取的id播放对应的声音
soundPool.play(shoot1ID,1,1,1,0,1);
soundPool.play(shoot2ID,1,1,1,0,1);
soundPool.play(shoot3ID,1,1,1,0,1);
1.3使用两种方式播放音乐
该案例比较简单,布局中只需两个按钮,一个用于播放MediaPlayer一个用于播放SoundPool。
我们需要将事先准备好的因为文件放到res/raw目录下,其中raw目录需要我们新创建。
代码清单如下:
publicclassMainActivityextendsActivity{
//声明MediaPlayer和SoundPool对象
privateMediaPlayermediaPlayer;
privateSoundPoolsoundPool;
privateintsoundID;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建MediaPlayer对象
mediaPlayer=newMediaPlayer();
try{
//设置音乐文件路径
mediaPlayer.setDataSource(Environment.getExternalStorageDirectory()+"/bgmusic.mp3");
//准备
mediaPlayer.prepare();
}catch(Exceptione){
e.printStackTrace();
}
//初始化SoundPool
soundPool=newSoundPool(1,AudioManager.STREAM_MUSIC,1);
//加载SoundPool音乐文件
soundID=soundPool.load(this,R.raw.shoot1,1);
}
publicvoidsoundPoolPlay(Viewview){
//播放SoundPool音乐
soundPool.play(soundID,1,1,0,0,1);
}
publicvoidmediaPlayerPlay(Viewview){
//判断当前音乐是否在播放
booleanisPlaying=mediaPlayer.isPlaying();
if(!
isPlaying){
//播放音乐
mediaPlayer.start();
}else{
Toast.makeText(this,"音乐正在播放中",0).show();
}
}
}
1.4案例-音乐播放器
:
制作一个播放器,能够播放/暂停/停止/重播音乐文件,并且添加一个SeekBar,音乐播放时,SeekBar的滚动条也会变化,拖动SeekBar,可更改声音播放的进度。
:
要实现此音乐播放器,必须严格按照上方的MediaPlayer状态流程图进行控制,否则非常容易使应用程序出错挂掉。
新创建一个Android工程《音乐播放器》
修改并使用默认布局文件,布局文件清单如下:
android="
xmlns:
tools="
android:
layout_width="match_parent"
android:
layout_height="match_parent"
android:
orientation="vertical"
tools:
context=".MainActivity">
android:
layout_width="wrap_content"
android:
layout_height="wrap_content"
android:
layout_gravity="center_horizontal"
android:
text="音乐播放器"/>
android:
id="@+id/et_path"
android:
text="/mnt/sdcard/bgmusic.mp3"
android:
layout_width="match_parent"
android:
layout_height="wrap_content"
android:
hint="请输入音乐路径"/>
android:
layout_width="match_parent"
android:
layout_height="wrap_content"
android:
orientation="horizontal">
android:
id="@+id/sb"
android:
layout_width="match_parent"
android:
layout_height="wrap_content"/>
android:
id="@+id/tv_time"
android:
layout_width="wrap_content"
android:
layout_height="wrap_content"
android:
layout_gravity="right"
android:
textColor="#ff0000"
android:
textSize="24sp"/>
使用并编写默认的MainActivity类,在该类中实现核心业务逻辑。
代码清单如下:
publicclassMainActivityextendsActivityimplementsOnSeekBarChangeListener{
privateEditTextet_path;
privateSeekBarsb;
privateTextViewtv_time;
privateMediaPlayerplayer;
privateintduration;
privatebooleanisUpdateBar;
//播放器的几个状态
privatestaticfinalintPLAYING=1;//播放状态
privatestaticfinalintPAUSING=2;//暂停状态
privatestaticfinalintSTOPPING=3;//停止状态
privateintCURRENT=0;//当前状态
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化界面控件
et_path=(EditText)findViewById(R.id.et_path);
sb=(SeekBar)findViewById(R.id.sb);
//给SeekBar绑定滑动事件
sb.setOnSeekBarChangeListener(this);
tv_time=(TextView)findViewById(R.id.tv_time);
}
//播放音乐
publicvoidplay(Viewview){
if(player!
=null){
if(CURRENT==PLAYING){
return;
}elseif(CURRENT==PAUSING){
player.start();
CURRENT=PLAYING;
updateSeekBar();
return;
}elseif(CURRENT==STOPPING){
player.reset();
player.release();
}
}
try{
//创建一个播放器对象
player=newMediaPlayer();
//获取音乐路径
Stringpath=et_path.getText().toString();
//给播放器设置音乐路径
player.setDataSource(path);
//设置音乐格式
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
//准备
player.prepare();
//获取音乐最大长度(毫秒单位)
duration=player.getDuration();
//给SeekBar设置最大值
sb.setMax(duration);
//格式化输出音乐长度
StringlastString=formatTime(duration);
tv_time.setText("00:
00/"+lastString);
//音乐开始播放
player.start();
//更新SeekBar
updateSeekBar();
}catch(Exceptione){
e.printStackTrace();
Toast.makeText(this,"音乐播放失败"+e,0).show();
}
}
//暂停
publicvoidpause(Viewview){
if(player!
=null&&CURRENT==PLAYING){
player.pause();
stopSeekBar();
CURRENT=PAUSING;
}
}
//停止播放
publicvoidstop(Viewview){
if(player!
=null){
if(CURRENT==PLAYING||CURRENT==PAUSING){
player.stop();
stopSeekBar();
sb.setProgress(0);
tv_time.setText("00:
00/"+formatTime(duration));
CURRENT=STOPPING;
}
}
}
//重新播放
publicvoidreplay(Viewview){
if(player!
=null){
stopSeekBar();
CURRENT=STOPPING;
play(view);
}
}
//停止SeekBar更新
privatevoidstopSeekBar(){
isUpdateBar=false;
}
//更新SeekBar
privatevoidupdateSeekBar(){
isUpdateBar=true;
newThread(newRunnable(){
@Override
publicvoidrun(){
while(isUpdateBar){
//每秒更新一次
SystemClock.sleep(1000);
if(player!
=null&&CURRENT==PLAYING){
sb.setProgress(player.getCurrentPosition());
//在主线程中运行如下代码更新EditText
runOnUiThread(newRunnable(){
@Override
publicvoidrun(){
Stringcurrent=formatTime(player.getCurrentPosition());
StringdurationString=formatTime(duration);
tv_time.setText(current+"/"+durationString);
}
});
}
}
}
}).start();
}
@Override
publicvoidonProgressChanged(SeekBarseekBar,intprogress,booleanfromUser){
if(player!
=null){
player.seekTo(progress);
}
}
//开始拖动SeekBar时停止更新SeekBar
publicvoidonStartTrackingTouch(SeekBarseekBar){
stopSeekBar();
}
//停止拖动SeekBar的时候将音乐定位到相应位置
publicvoidonStopTrackingTouch(SeekBarseekBar){
if(player!
=null){
player.seekTo(seekBar.getProgress());
updateSeekBar();
}
}
//工具函数格式化播放时间
privateStringformatTime(intcurrent){
intsecond=current/1000;
intminute=second/60;
second=second-minute*60;
StringBuildersb=newStringBuilder();
sb.append(minute>10?
minute+"":
"0"+minute);
sb.append(":
");
sb.append(second>10?
second:
"0"+second);
returnsb.toString();
}
}
运行上面的工程,效果图如下:
2.视频播放(★★)
2.1使用MediaPlayer+SurfaceView播放视频文件
:
在这里视频播放依然通过MediaPlayer类,为了方便演示,我们直接使用1.4章节中的创建的工程,只需在布局文件添加SurfaceView控件即可。
android:
layout_width="match_parent"
android:
layout_height="match_parent"
android:
id="@+id/sv"
/>
我们直接在1.4章节的代码基础上进行修改,修改MainActivity类,这里只给出不同的代码片段:
添加如下变量的声明
privateSurfaceViewsv;
privateSurfaceHolderholder;
在play()方法中添加如下代码
//设置输出画面
player.setDisplay(holder);
获取SurfaceView对象,并设置缓存方式
sv=(SurfaceView)findViewById(R.id.sv);
holder=sv.getHolder();
/**
*SurfaceView内部采用双缓冲区
*设置SurfaceView不维护自己的缓存区,使用屏幕的渲染引擎将内容推*送到用户面前
*/
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
运行该工程,效果图如下:
2.2使用VideoView控件显示视频
VideoView跟MediaPlayer相比播放视频步骤要简单的多,因此VideoView自己提供了播放,暂停、快进、快退、进度条等方法。
使用起来要方便的很多。
:
1、设置布局文件,布局文件比较简单,因此这里只给你VideoView标签。
android:
id="@+id/vv"
android:
layout_width="match_parent"
android:
layout_height="match_parent"/>
2、设置VideoView的播放文件路径和媒体控制器,调用start方法即可播放媒体文件。
//实例化VideoView对象
vv=(VideoView)findViewById(R.id.vv);
//从界面获取播放路径
et_path=(EditText)findViewById(R.id.et_path);
//给VideoView设置视频路径
vv.setVideoPath(et_path.getText().toString());
//设置VideoView控制器,我们当前类实现了MediaPlayerControl接口
vv.setMediaController(newMediaController(this));
//开始播放
vv.start();
//设置当前播放器窗口设置为焦点
vv.requestFocus();
3、覆写MediaPlayerControl接口中的抽象方法
@Override