媒体播放及Media Player

2020-04-09 17:26:31 

  1. MediaPlayer API介绍
  2. 音频播放
  3. 视频播放及VideoView,SurfaceView

MediaPlayer API介绍

    Mediaplayer可用来播放video,audio,另外可使用AudioManager(提供铃声和音量的控制)管理音频资源和输出

    MediaPlayer状态转换图:

(上图双箭头表示异步调用

MediaPlayer 可在任何状态设置相关的事件监听器, 同时提供了一个方便的静态方法create来创建Media Player实例并使其进入Prepared状态。

通过MediaPlayer构造函数所创建的实例处于Idle状态,此时需要调用setDataSource使其进入Initialzed状态,然后可调用prepare方法进入Prepared状态,或其异步版本的prepare方法(prepareAsync),调用prepareSync会进入Preparing状态,使用prepareAsync方法需要设置OnPreparedListener监听器来变为Prepared状态,进入Prepared 状态就可以调用start方法来播放媒体文件。

音频播放

  • 播放音频
 1     MediaPlayer player = new MediaPlayer();//Idle状态
 2             //在使用app自带资源时
 3     //常使用create简便方法实例化Media Player,并且进入Prepared状态,player = create(this,R.id.resId);
 4              //在使用assets 目录的文件时 
 5     //使用AssetsManager来管理,可使用getAssets()得到AssetsManager的实例assetsManager ,
 6     //AssetsFileDescriptor afd = assetsManager.openFd(String fileName);将afd作为参数传递给create或setDataSource
 7      
 8     //另外create和setDataSource使用String path作为参数时,path指的是文件系统路径,通常是sdCard目录的媒体文件
 9     player.setDataSource(…)//设置资源,进入Initialized状态
10     player.prepare() //进入Prepared状态
11     //or 调用prepareAsync()进入preparing状态,可以设置监听器 setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener).
12     Player.start()//开始播放 进入started状态

 

    • 音频特效AudioEffect

      AudioEffect是Android框架提供的音效控制的基类,应使用其子类来控制特定音效。要使用音效 音效的实例必须调用setEnabled (Boolean enabled)来启用。每种音效都必须或得对应得音频的sessionId,sessionId可通过MediaPlayer.getAudioSessionId()获取。

      • AcousticEchoCanceler:    AEC 取消回声控制器
      • AutomaticGainControl:    自动增益控制器
      • NoiseSuppressor:    噪声压制控制器
        上面三个子类只需使用其对应的静态方法create(int audioSession)创建相应实例,然后调用isAvailable()判断是否可用,再调用setEnabled(Boolean enabled)方法启用相应效果。(setEnabled方法由基类Audio Effect提供)
1 AcousticEchoCanceler aec =AcousticEchoCanceler.create(mediaPlayer.getAudioSessionId());
2 if(aec.isAvailable){
3     aec.setEnable(true);
4 }

 

 

其余子类需要调用其构造方法来创建实例

  • BassBoost 重低音
    1 BassBoost bassBoost = new BassBoost(0,player.getAudioSessionId());
    2 bassBoost.setEnabled(true);//
    3 Basst.setStrength(strength);// 设置强度,范围在0-1000,0最小,1000最大 
  • Equalizer 均衡器

           

 1 //通过MediaPlayer.getAudioSessionId()得到音频的AudioSessionId,在Equalizer实例化时将AudioSessionId传入构造参数
 2 Equalizer equalizer = new Equalizer(0,meidiaPlayer.getAudioSessionId);
 3         //启用均衡器Equalizer
 4 equalizer.setEnabled(true);
 5 //获取频带增益范围
 6 short[] bandLevelRange = equalizer.getBandLevelRange();
 7 short minLevel = bandLevelRange[0];
 8 short maxLevel = bandLevelRange[1];
 9  
10         //getNumberOfBands 得到Equalizer引擎支持的频带数量
11 for (short band =0 ; i < equalizer.getNumberOfBands();i++){
12  
13     //getCenterFreq():获取band对应的频率     
14       int  frequency = equalizer.getCenterFreq(band);
15 }
16 equalizer.setBandLevel(shot band,short level);//为特定频率设置增益,频率为band所对应的frequency
  • 在音频应用中使用 VolumeShaper 来执行渐强、渐弱、渐强渐弱、降低音量以及其他短暂的自动音量转换。VolumeShaper 类在 Android 8.0(API 级别 26)及更高版本中可用。通过对 AudioTrackMediaPlayer 的实例调用 createVolumeShaper() 来创建 VolumeShaperVolumeShaper 仅对创建它的 AudioTrack 或 MediaPlayer 生成的音频起作用

    VolumeShaper 的行为由它的 VolumeShaper.Configuration 定义。该配置指定了音量曲线、插值器类型和持续时间。

 1 //创建配置
 2 VolumeShaper.Configuration configuration = new VolumeShaper.Configuration.Builder()
 3                     .setCurve(new float[]{0.0f,0.5f,1.0f},new float[]{0.f, 1.f,0.f})
 4                     .setDuration(1000*60*1)
 5                     .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
 6                     .build();
 7 //创建volumeShaper
 8  VolumeShaper volumeShaper = player.createVolumeShaper(configuration);
 9 //应用volumeShaper到音频
10  volumeShaper.apply(VolumeShaper.Operation.PLAY);
11 //替换配置
12 boolean join = true;
13 volumeShaper.replace(newConfig, VolumeShaper.Operation.PLAY, join);
14 //关闭volumeShaper
15 volumeShaper.close();
  • SoundPool为应用程序管理和播放音频资源,预先将音频加载到内存,低时延、cpu占用少。通常用于游戏播放短音频,支持速率、音量、音频优先级,声道、循环设置。

    使用SoundPool.Builder构造实例,构造函数已被废弃。使用SoundPool.Builder时有一下几个方法:setAudioAttribute方法需要一个AudioAttribute对象。

     

AudioAttribute封装了描述音频流信息的属性的集合,使用AudioAttribute.Builder创建AudioAttribute实例。使用setUsage设置使用场景,setContentType设置内容类型,build创建AudioAttribute实例。

SoundPool的方法load方法加载音频并返回一个int值,这个int 值是音频的streamID。播放时调用SoundPool的play方法。第一个参数soundID即是load方法加载音频时返回的代表音频的streamID。第二三个参数时左声道和右声道,0.0f-1.0f。loop代表循环次数(播放次数=循环次数+1),为-1时一直循环。rate:播放速度0.5-2.0,默认为1。

 

1 AudioAttributes attr = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_GAME).
2 setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
3 SoundPool soundPool = new SoundPool.Builder().setAudioAttributes(attr).setMaxStreams(10).build();
4  int soundID = soundPool.load(…);//加载音频
5 soundPool.play(soundID,1.0,1.0,0,0,1);//播放音乐
6 //可将所加载的音频的streamID放入容器(List,Map),保存streamID。

 

  

   

 

视频播放及VideoView,SurfaceView

  • VideoView

    在使用videoView时(和布局主题有关)会导致有白边现象,可以实现VideoView的子类(自定义View),重写onMeasure()方法。

 

 1 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 2     super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 3 //获取系统服务的WindowManager
 4     WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
 5     assert wm != null;
 6 //将所得到的像素大小保存在point中
 7     Point point = new Point();
 8     wm.getDefaultDisplay().getSize(point);
 9 //设置绘制的大小
10     setMeasuredDimension(point.x,point.y);

 

 

获取当前屏幕的大小与WindowManager,Display,DisplayMetris这三个类有关。getContext.getSystemService(Context.WINDOW_SERVICE)取得windowManager,windowManager.getDefaultDisplay()返回一个Display。Display中有许多获得窗口屏幕大小的方法:getSize,getMetrics。

 

 

使用自定义的VideoView播放视频

 

 1 //MediaController提供图形界面对视频的控制
 2 MediaController mediaController = new MediaController(this);
 3 //设置视频
 4 fullScreenVideoView.setVideoURI(Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.fat));
 5 //将meidiaController与videoView联系起来
 6 mediaController.setMediaPlayer(fullScreenVideoView);
 7 fullScreenVideoView.setMediaController(mediaController);
 8 //打开屏幕,获取焦点
 9 fullScreenVideoView.requestFocus();
10 //播放视频
11 fullScreenVideoView.start();

 

 

 

   

  • SurfaceView

    VideoView是SurfaceView的子类

    Surface是可以在子线程渲染更新界面,surfaceView.getHolder的返回值就是一个surfaceHolder,也是surfaceView的核心, surfaceHolder.addCallback()为其添加一个回调,在这个回调中包含surface的完整的生命周期:surfaceCreated、surfaceChanged、surfaceDestroy。若使用绘画子线程必须,子线程必须和主线程同步,只有当surface状态在生命周期只能子线程才能访问surface。

 

 1 mediaPlayer = MediaPlayer.create(this,R.raw.fat);
 2 surfaceView.getHolder().setKeepScreenOn(true);
 3 surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
 4     @Override
 5      public void surfaceCreated(SurfaceHolder holder) {
 6         DisplayMetrics metrics = new DisplayMetrics();
 7         MainActivity.this.getWindowManager().getDefaultDisplay().getMetrics(metrics);
 8         surfaceView.setLayoutParams(new ConstraintLayout.LayoutParams(metrics.widthPixels,
 9                 mediaPlayer.getVideoHeight()*metrics.widthPixels/mediaPlayer.getVideoWidth()));
10         mediaPlayer.setDisplay(surfaceView.getHolder());
11         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
12     }
13     @Override
14      public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
15     }
16     @Override
17      public void surfaceDestroyed(SurfaceHolder holder) {
18     }
19 });

17:22:36

翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 谷歌翻译(国内)

 

翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 谷歌翻译(国内)

 

翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 谷歌翻译(国内)

 

翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 谷歌翻译(国内)

 

翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 谷歌翻译(国内)

posted @ 2020-04-09 17:05  lrllzp  阅读(787)  评论(0)    收藏  举报