Android实现播放本地视频

Android实现播放本地视频

    • 一、目标
    • 二、播放视频
      • 1. 播放单独视频
      • 2. 暂停播放视频
      • 3. 处理视频播放结束
      • 4. 处理Detach事件
      • 5. 处理onStop事件
    • 三、播放多个视频
    • 四、视频和音频同时播放
    • 五、处理扬声器
    • 六、处理录音
    • 七、开发过程回顾
    • 八、接下来
    • 九、Finally

完成《Android实现录像功能》和《Android实现选择视频功能》后,已经实现了神马笔记插入视频的功能,接下来完成视频笔记的最后一个功能——播放。

一、目标

播放视频笔记中的视频。

二、播放视频

播放本地视频可以使用VideoViewMediaPlayer + SurfaceView两种方式。

目前VideoView已经足够满足要求,因此采用VideoView方式。

1. 播放单独视频

设置视频路径setVideoURI()后,调用start()方法即可播放视频。

VideoItem item = this.getItem();
if (item == null) {
  return;
}

if (!isReady) {
  videoView.setVideoURI(item.getUri());
  isReady = true;
}

{
  videoView.start();

  actionBtn.setVisibility(View.INVISIBLE);
  //            photoView.setVisibility(View.INVISIBLE); // when rendering start, make it invisible
  videoView.setVisibility(View.VISIBLE);
}

{
  item.setPlaying(true);
}

2. 暂停播放视频

调用pause()接口,暂停播放。

VideoItem item = this.getItem();
if (item == null) {
  return;
}

if (videoView.isPlaying()) {
  videoView.pause();

  actionBtn.setVisibility(View.VISIBLE);
}

3. 处理视频播放结束

释放资源并调整界面。

VideoItem item = this.getItem();
if (item != null) {
  item.setPlaying(false);
}

{
  actionBtn.setVisibility(View.VISIBLE);
  photoView.setVisibility(View.VISIBLE);
  //            videoView.setVisibility(View.INVISIBLE); // keep it visible to avoid black slash
}

{
  videoView.stopPlayback();
  this.isReady = false;
}

4. 处理Detach事件

VideoView在detach时,会释放MediaPlayer,不进行处理的话会显示黑屏。

因此需要调整界面。

public void surfaceDestroyed(SurfaceHolder holder)
{
  // after we return from this we can't use the surface any more
  mSurfaceHolder = null;
  if (mMediaController != null) mMediaController.hide();
  release(true);
}
super.onViewDetachedFromWindow();

VideoItem item = this.getItem();
if (item != null) {
  item.setPlaying(false);
}

{
  actionBtn.setVisibility(View.VISIBLE);
  photoView.setVisibility(View.VISIBLE);
  videoView.setVisibility(View.INVISIBLE);
}

{
  videoView.stopPlayback();
  this.isReady = false;
}

5. 处理onStop事件

Activity切换到后台时,同样会释放MediaPlayer,因此需要调整界面。

三、播放多个视频

播放单个视屏时,需要处理用户播放及暂停视频,以及视频播放结束、Detach事件、onStop事件等事件。

Android支持同时播放多个视频,使用多个VideoView可以同时播放多个视频。

神马笔记对视频播放进行了显示,同一个时间只能播放一个视频。

因此,播放新视频的同时,停止上一个视频的播放。

public void setPlayingItem(ChatItem item, boolean stopPrevious) {
  if (playingItem == item) {
    return;
  }

  ChatItem previous = playingItem;
  this.playingItem = item;

  if (previous != null && stopPrevious) {
    int position = previous.getParent().indexOf(previous);
    recyclerView.getAdapter().notifyItemChanged(position);

    ChatViewHolder holder = ChatViewHolderUtils.find(recyclerView, previous);
    if (holder != null) {
      holder.stop();
    }
  }
}

四、视频和音频同时播放

Android使用多个MediaPlayer可以同时播放视频和音频。

同样的,神马笔记对此进行了限制,或者播放视频,或者播放音频,二选一。

  • 播放视频时,停止音频播放
public void setPlaying(boolean value) {
  VideoHelper videoHelper = getVideoHelper();

  if (value) {

    // stop audio
    {
      parent.getTapeHelper().stop();
      parent.getTapeHelper().resetSpeaker(); 
    }

    {
      videoHelper.setPlayingItem(this, true);
    }

  } else {
    if (isPlaying()) {

      // reset speaker
      {
        parent.getTapeHelper().setSpeakerOn(parent.getTapeHelper().isSpeakerOn(), true);
      }

      {
        videoHelper.setPlayingItem(null, false);
      }
    }
  }
}
  • 播放音频时,停止视频播放
public void start() {
  {
    TapeHelper tapeHelper = getTapeHelper();

    tapeHelper.setSpeakerOn(tapeHelper.isSpeakerOn(), true);
    tapeHelper.setWakeLock(true);
    tapeHelper.setScreenOn(true);
  }

  {
    parent.getVideoHelper().stop();
  }

  {
    AudioPlayer player = this.getAudioPlayer();
    player.setTarget(this.getFile());
    player.start();
  }
}

五、处理扬声器

播放音频时,神马笔记允许选择听筒或者扬声器进行输出。

但播放视频只使用扬声器。

六、处理录音

Android允许录音和播放视频同时进行。

同样的,神马笔记对此进行了限制。

同样的,二选一。

void requestTape() {
  this.tapeHelper.stop();
  this.videoHelper.stop();
  this.tapeHelper.resetSpeaker();

  PermissionHelper helper = new PermissionHelper(getActivity());
  helper.setPermission(Manifest.permission.RECORD_AUDIO);

  final boolean isGranted = helper.isGranted();
  PermissionHelper.OnPermissionListener consumer = (h) -> {

    bottomBar.chatBar.setVisibility(View.INVISIBLE);

    popupTape.show(isGranted);
  };

  String requestMsg = "请允许录制音频,以发送语音。";
  String deniedMsg = "请在「权限管理」,设置允许「麦克风」,以发送语音。";

  helper.setRequestMessage(requestMsg);
  helper.setDeniedMessage(deniedMsg);
  helper.setOnPermissionListener(consumer);
  helper.request();
}

七、开发过程回顾

首先,我们处理了单个视频的播放,允许用户播放及暂停,然后处理视频播放结束后,用户可以重新开始播放,并且处理了detach和onStop两个事件。

接下来,处理多个视频播放,对此进行了限制,同一时间只能播放一个视频。

然后,处理视屏和音频播放问题,同一时间只能播放一种。

再来,处理扬声器问题,播放视频时,只会将音频输出到扬声器。

最后,处理视频和录音的问题,同样是二选一。

分类 关系 说明
视频 单个 处理用户播放及暂停,并且处理结束事件、detach事件和onStop事件。
多个 一次只允许播放一个视频。
相关 音频 视频和音频,二选一。
扬声器 只输出到扬声器,不能使用听筒。
录音 视频和录音,二选一。

八、接下来

提交视频笔记版本测试,顺利的话,明天就能发布。

九、Finally

须菩提。
菩萨应如是布施。不住于相。
何以故。
若菩萨不住相布施。
其福德不可思量。

你可能感兴趣的:(神马笔记)