媒体播放及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)及更高版本中可用。通过对 AudioTrack 或 MediaPlayer 的实例调用 createVolumeShaper() 来创建 VolumeShaper,VolumeShaper 仅对创建它的 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  阅读(813)  评论(0)    收藏  举报