91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android進階:自定義視頻播放器開發(下)

發布時間:2020-07-11 04:58:21 來源:網絡 閱讀:639 作者:十年開發 欄目:移動開發

上一篇文章我們主要講了視頻播放器開發之前需要準備的一個知識,TextureView,用于對圖像流的處理。這篇文章開始構建一個基礎的視頻播放器。

一、準備工作

在之前的文章已經說過了,播放器也是一個view,我們要在這個view上播放視頻流。所以我們要自定義一個簡單的viewgroup,比如繼承FrameLayout。還出就是布局簡單,其他控件可以往上面添加。大家見過的視頻播放器的控制器都是放在視頻的上方的。這樣就是用FrameLayout布局是最好的。

class SmallVideoPlayer extends FrameLayout

二、初始化TextureView

這是一個用于承載顯示‘數據流’的View,它不會創建新的窗口來顯示內容。它是將內容流直接投放到View中,并且可以和其它普通View一樣進行移動,旋轉,縮放,動畫等變化。
TextureView初始化方式如下,并且我們這個播放器View要實現其監聽方法:

class SmallVideoPlayer extends FrameLayout implements TextureView.SurfaceTextureListener

  private void initTextureView() {
        if (mTextureView == null) {
            mTextureView = new TextureView(mContext);
            mTextureView.setSurfaceTextureListener(this);
        }
    }

然后我們把這個TextureView添加到我們的視頻播放器的view上,并且設置跟視頻播放器View一樣大小:

    private void addTextureView() {
        removeView(mTextureView);
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT,
                Gravity.CENTER);
        addView(mTextureView, 0, params);
    }

三、初始化播放器內核

一個公司想要實現機的播放器內核需要一定的成本,所以大部分公司都選擇使用第三方的內核,比如bilibili開源的ijkplayer。ijkplayer是一個基于FFmpeg的輕量級Android/iOS視頻播放器。FFmpeg的是全球領先的多媒體框架,能夠解碼,編碼,轉碼,復用,解復用,流,過濾器和播放大部分的視頻格式。它提供了錄制、轉換以及流化音視頻的完整解決方案。這里我們也用它。

在項目module的gradle里面添加依賴:

    implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.3'
    implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.3'
    implementation 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.3'
    implementation 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.3'

編譯成功之后我們就可以在代碼里面用它了,這個也很簡單一般不會出什么問題。ijplayer里面提供了一個IMediaPlayer,我們初始化它即可:

    private void initMediaPlayer() {
        if (mMediaPlayer == null) {
            mMediaPlayer = new IjkMediaPlayer();
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        }
    }

準備工作都做好了,我們要在什么時候開始播放呢?當然是TextureView準備好之后就可以播放了,TextuerView的draw方法中會調用TextureLayer layer = getTextureLayer();方法,而getTextureLayer()這個方法中當surface創建成功之后會執行我們實現的接口方法:

 if (mListener != null && createNewSurface) {
                mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
            }

從上面代碼可以看出當我們設置了mListener,并且創建surface成功之后會為我們回調onSurfaceTextureAvailable方法,并傳遞給我們一個mSurface及其寬高。那我們在這個方法里播放視頻就可以了:

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        if (mSurfaceTexture == null) {
            mSurfaceTexture = surface;
            openMediaPlayer();
        } else {
            mTextureView.setSurfaceTexture(mSurfaceTexture);
        }
    }

我們自己創建一個SurfaceTexture對象存儲TextureView給我傳遞的SurfaceTexture對象,然后開啟視頻播放。如果你自己實現了SurfaceTexture,你也可以用你自己的。

    private void openMediaPlayer() {
        // 屏幕常亮
        setKeepScreenOn(true);
        // 設置dataSource
        try {
            mMediaPlayer.setDataSource(mContext.getApplicationContext(), Uri.parse(mUrl));
            if (mSurface == null) {
                mSurface = new Surface(mSurfaceTexture);
            }
            mMediaPlayer.setSurface(mSurface);
            mMediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

使用ijplayer播放視頻很簡單,只要為其設置數據源即可。但是為了能讓視頻顯示出來,也就是能在view上播放出來,我們需要使用Surface。
創建對象private Surface mSurface;,傳入剛才存儲的SurfaceTexture對象:mSurface = new Surface(mSurfaceTexture);,然后把這個surface對象傳遞給播放器即可,最后使用播放器開始播放,注意這個方法是同步的。
完成以上步驟,簡單的視頻播放器就可以完成了。

代碼:
我們把代碼進行整理如下:

播放器

public class SmallVideoPlayer extends FrameLayout implements TextureView.SurfaceTextureListener {
    private TextureView mTextureView;
    private SurfaceTexture mSurfaceTexture;
    private Surface mSurface;
    private AudioManager mAudioManager;
    private IMediaPlayer mMediaPlayer;
    private Context mContext;
    private String mUrl;

    public SmallVideoPlayer(@NonNull Context context) {
        this(context, null);
    }

    public SmallVideoPlayer(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public SmallVideoPlayer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
    }

    public void setUp(String url) {
        mUrl = url;

    }

    public void start() {
        initAudioManager();
        initMediaPlayer();
        initTextureView();
        addTextureView();
    }

    private void initAudioManager() {
        if (mAudioManager == null) {
            mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                mAudioManager.requestAudioFocus(new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).build());
            } else {
                mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
            }
        }
    }

    private void initMediaPlayer() {
        if (mMediaPlayer == null) {
            mMediaPlayer = new IjkMediaPlayer();
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        }
    }

    private void initTextureView() {
        if (mTextureView == null) {
            mTextureView = new TextureView(mContext);
            mTextureView.setSurfaceTextureListener(this);
        }
    }

    private void addTextureView() {
        removeView(mTextureView);
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT,
                Gravity.CENTER);
        addView(mTextureView, 0, params);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        if (mSurfaceTexture == null) {
            mSurfaceTexture = surface;
            openMediaPlayer();
        } else {
            mTextureView.setSurfaceTexture(mSurfaceTexture);
        }
    }

    private void openMediaPlayer() {
        // 屏幕常亮
        setKeepScreenOn(true);

        // 設置dataSource
        try {
            mMediaPlayer.setDataSource(mContext.getApplicationContext(), Uri.parse(mUrl)/*, mHeaders*/);
            if (mSurface == null) {
                mSurface = new Surface(mSurfaceTexture);
            }
            mMediaPlayer.setSurface(mSurface);
            mMediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return mSurfaceTexture == null;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }
}

使用布局:
在activity中的布局加上即可

    <com.example.ycm.smallvideoplayer.smallvideoplayer.SmallVideoPlayer
        android:id="@+id/small_video_player"
        android:layout_width="match_parent"
        android:layout_height="200dp" />

在activity中獲取播放器view,然后設置一個視頻URL,開啟播放即可。

    SmallVideoPlayer mSmallVideoPlayer; = findViewById(R.id.small_video_player);
    mSmallVideoPlayer.setUp("http://tanzi27niu.cdsb.mobi/wps/wp-content/uploads/2017/05/2017-05-17_17-33-30.mp4");
    mSmallVideoPlayer.start();

以上就完成了視頻播放器的初體驗。其實你會發現這是多么簡單啊。實際上來說一個高級開發人員并沒有比你高明多少,他們比你多的其實只是經驗和思路。所以想要從初中級開發跳躍到高級開發,需要你不斷的思考,獨立實現業務需求。如果給你一個大模塊,你能利用你的知識,和網絡獲取的資料就能實現,你離高級開發工程師就不遠了。

推薦閱讀

Android進階:自定義視頻播放器開發(上)

最后

需要相關教學視頻及源碼,可以點擊鏈接加入群聊【Android技術開發交流】:https://jq.qq.com/?_wv=1027&k=5PWTvm9, 找群管理免費領取一下,歡迎進群一起學習交流
Android進階:自定義視頻播放器開發(下)

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

论坛| 剑河县| 峨山| 临清市| 夏津县| 仙居县| 盐城市| 长岛县| 吉水县| 克东县| 察雅县| 余干县| 呼图壁县| 汝城县| 观塘区| 项城市| 涞水县| 连江县| 临夏县| 溧阳市| 凌海市| 邵阳县| 象州县| 清涧县| 彭山县| 确山县| 彭泽县| 霞浦县| 清河县| 古浪县| 祁东县| 全椒县| 务川| 德昌县| 黎川县| 吉木萨尔县| 静安区| 清水河县| 博客| 平江县| 清原|