Android播放器

项目起始阶段,为了追求早点上线,使用第三方库讲的是拿来就用,结果到了优化重构阶段或者因为一些原因不得不换第三方库时,那就头疼了。
这里可以举很多例子,像图片加载库、网络请求库、第三方统计库,如果不进行封装,而是直接调用,代码耦合性非常高,也不利于以后扩展。
以上三个例子可以自己写个类包装下,就不再赘述了。而视频播放,同时涉及到MediaPlayer状态回调和所在控件的生命周期,更为复杂一点,下面我做了一个简单的分享,不过足以应付大部分的现实情况。


项目(https://github.com/wanghy360/HyVideoPlayer)结构如下:

  • hyvideolibrary :播放器抽象,重连机制的逻辑
  • ksylibrary:金山播放器的实现
  • ijklibraray:Bilibili播放器的实现
  • app:demo效果

在hyvideolibrary定义了播放器的所有行为以及它的回调方法。

/**
 * Created by Wanghy on 2017/9/11
 * 播放器抽象类,定义了播放器的行为方法
 *
 * @param <T> 播放器View
 */
public abstract class Player<T> {
    protected Callback callback;

    /**
     * 初始化
     *
     * @param realPlayer 播放器View
     */
    public abstract void init(T realPlayer);

    /**
     * @return 播放器View
     */
    public abstract T getRealPlayer();

    /**
     * 开始播放
     *
     * @param liveUrl 视频Url
     */
    public abstract void startVideo(String liveUrl);

    /**
     * 结束播放
     */
    public abstract void stopPlay();

    /**
     * 后台播放
     */
    public abstract void runInBackground();

    /**
     * 前台播放
     */
    public abstract void runInForeground();

    /**
     * 释放资源
     */
    public abstract void release();

    /**
     * reset播放
     */
    public abstract void reset();

    /**
     * 此方法务必调用
     */
    public void setCallBack(Callback callback) {
        this.callback = callback;
    }

    public interface Callback {
        /**
         * 播放准备
         */
        void onPrepared();

        /**
         * 缓冲开始
         */
        void onBufferingStart();

        /**
         * 缓冲结束
         */
        void onBufferingEnd();

        /**
         * 视频展现开始
         */
        void onRenderingStart();

        /**
         * 播放结束
         */
        void onCompletion();

        /**
         * 播放出错
         */
        void onError();
    }
}

还有一个VideoPlayer抽象类,事实上这个才是播放视频。Player抽象类方法较少,适用于rtmp视频流。

在PlayerPresenter里实现了重连机制,这个逻辑与播放器无关,所以独立出来。

说到Presenter,这里实现了部分MVP架构,View就是播放器所在的组件(例如Activity,Fragment乃至View),Presenter包含播放器所有代码逻辑,由于数据只有一个Url,所以并没有定义model。

自己可以在继承自PlayerPresenter的MyPlayerPresenter里,增加自己的代码逻辑。这里只是显示了Toast。

public class MyPlayerPresenter<V> extends PlayerPresenter<V, MyPlayView> {

    public MyPlayerPresenter(MyPlayView view) {
        super(view);
    }

    @Override
    protected boolean isBlockReLoad() {
        return false;
    }

    @Override
    protected void reLoadLiveFail() {
        Toast.makeText(view.getViewActivity(), "reLoadLiveFail", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRenderingStart() {
        super.onRenderingStart();
        Toast.makeText(view.getViewActivity(), "onRenderingStart", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void reConnect() {
        super.reConnect();
        Toast.makeText(view.getViewActivity(), "reConnect", Toast.LENGTH_SHORT).show();
    }
}

2个播放器实现以后,在PlayerActivity将到Presenter与View关联起来,除了要在继承自PlayerActivity的Activity里初始化videoView,2个播放器并没有其他的不同。 

//ksylive
videoView = (KSYTextureView) findViewById(R.id.id_ksy_player);
//ijkplayer
videoView = (IjkVideoView) findViewById(R.id.id_ijk_player);

共同部分:

import android.os.Bundle;

import com.github.wanghy360.hyvideolibrary.player.Player;
import com.github.wanghy360.player.presenter.MyPlayerPresenter;
import com.github.wanghy360.player.view.MyPlayView;

/**
 * Created by Wanghy on 2017/9/15
 */
public abstract class PlayerActivity<V> extends BaseActivity implements MyPlayView<PlayerActivity> {
    protected V videoView;
    private MyPlayerPresenter<V> myPlayerPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    protected void init(Player<V> player) {
        myPlayerPresenter = new MyPlayerPresenter<>(this);
        myPlayerPresenter.subscribe(videoView, player);
        myPlayerPresenter.startVideo("rtmp://live.hkstv.hk.lxdns.com/live/hks");
    }

    @Override
    protected void onPause() {
        super.onPause();
        myPlayerPresenter.runInBackground();
    }

    @Override
    protected void onResume() {
        super.onResume();
        myPlayerPresenter.runInForeground();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        myPlayerPresenter.unSubscribe();
    }

    @Override
    public PlayerActivity getViewActivity() {
        return this;
    }
}

分享就介绍到这里了,下一个博客应该会写一个功能全面的播放界面,涉及到横竖切换,音量亮度调节,重力感应。

转载于:https://my.oschina.net/u/3686484/blog/1538179

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值