Androidオーディオおよびビデオ開発シリーズ-VideoViewの使用

一緒に書く習慣を身につけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して4日目です。クリックしてイベントの詳細をご覧ください

VideoViewの紹介

私は以前、ビデオを再生する機能を実現するためにMediaPlayer+の使用を紹介しました。簡単なビデオ再生機能を実現するための公式パッケージコンポーネントSurfaceViewを偶然見つけました。 +形式はビデオファイルの再生を制御するためにも使用されます。使い方は比較的シンプルで、動画を再生するだけのシナリオに適していますが、その限られた機能は、動画の明るさの調整など、他の機能には適していません。VideoViewMediaPlayerSurfaceViewMediaPlayer

MediaController

再生コンポーネントに加えて、ビデオ再生、一時停止、早送り、早戻しなどの機能をサポートする、ビデオ再生用の再生操作バー機能を提供するコンポーネントVideoViewもあります。MediaControllerさらに、ビデオを再生するために指定された位置にドラッグできるプログレスバー機能も提供します。

使用する

VideoViewこのパッケージMediaPlayerは、同様のMediaPlayerAPIも提供します。たとえばstart、メソッドはビデオを再生する機能でもありますがsetOnpreparedListener、メソッドを呼び出してメソッドを実行する前にコールバック結果を設定することをお勧めします。メソッドは、メソッドが呼び出さsetVideoPathれた後にアクティブに実行されます。prepareAsync開発者が多くの機能を内部でカプセル化して実装するのにVideoView役立ちます。実際、内部ソースコードから学習して、より包括的でより完全な自作プレーヤーを実現することもできます。

一般的なAPI 説明する
setVideoPath ビデオアセットを設定する
始める 遊ぶ
一時停止 一時停止
履歴書 リプレイ
探す 指定された場所でプレイ
isPlaying ビデオが再生されているかどうか
getCurrentPosition 現在の再生位置を取得します
setMediaController MediaControllerを設定します
setOnpreparedListener ビデオ読み込み完了イベントをリッスンする
// 实例化videoView     
videoView = new VideoView(this);
Uri uri = Uri.fromFile(new File("sdcard/DCIM","新世纪福音战士24.mp4"));
//加载视频资源
videoView.setVideoURI(uri);
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.addView(videoView);
setContentView(linearLayout);
//设置监听
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        //回调成功并播放视频
        videoView.start();
    }
});
//创建操作栏
MediaController mediaController = new MediaController(this);
videoView.setMediaController(mediaController);
mediaController.setMediaPlayer(videoView);
复制代码

a5a4ba6ebe7731127c5f2f64eb01b134.jpg

ソースコード分析

VideoView2つのコンポーネントがカプセル化MediaControllerされたので、以前に実装が試みられた多くの関数が、それらがどのように実装されているかを確認するために使用プロセスで見つかります。

進捗状況の表示

MediaController表示されると、呼び出し元のメソッドshow内にpost(mShowProgress);メソッドが表示されます。

public void show(int timeout) {
    if (!mShowing && mAnchor != null) {
        setProgress();
        if (mPauseButton != null) {
            mPauseButton.requestFocus();
        }
        disableUnsupportedButtons();
        updateFloatingWindowLayout();
        mWindowManager.addView(mDecor, mDecorLayoutParams);
        mShowing = true;
    }
    updatePausePlay();

    // cause the progress bar to be updated even if mShowing
    // was already true.  This happens, for example, if we're
    // paused with the progress bar showing the user hits play.
    post(mShowProgress);

    if (timeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
        removeCallbacks(mFadeOut);
        postDelayed(mFadeOut, timeout);
    }
}
复制代码

これmShowProgressは1つRunnableであり、内部遅延がそれ自体を呼び出して更新することがわかりsetProgress()ます。setProgress()再生の進行状況を読み取り、MediaPlayer再生情報を更新する方法です。

private final Runnable mShowProgress = new Runnable() {
    @Override
    public void run() {
        int pos = setProgress();
        if (!mDragging && mShowing && mPlayer.isPlaying()) {
            postDelayed(mShowProgress, 1000 - (pos % 1000));
        }
    }
};
复制代码

プレイサイズの適応

再生サイズの適応をカスタマイズする前に、VideoView開発者が内部でビデオ再生の適応を実現するのに直接役立ちます。詳細なコードはonMeasure直接。コードのおおよそのアルゴリズムはVideoView、レイアウトの幅と高さ、およびビデオの幅と高さを比較することによって、計算された幅と高さを書き直すことVideoViewです。

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
    //        + MeasureSpec.toString(heightMeasureSpec) + ")");

    int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
    int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
    if (mVideoWidth > 0 && mVideoHeight > 0) {

        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
            // the size is fixed
            width = widthSpecSize;
            height = heightSpecSize;

            // for compatibility, we adjust size based on aspect ratio
            if ( mVideoWidth * height  < width * mVideoHeight ) {
                //Log.i("@@@", "image too wide, correcting");
                width = height * mVideoWidth / mVideoHeight;
            } else if ( mVideoWidth * height  > width * mVideoHeight ) {
                //Log.i("@@@", "image too tall, correcting");
                height = width * mVideoHeight / mVideoWidth;
            }
        } else if (widthSpecMode == MeasureSpec.EXACTLY) {
            // only the width is fixed, adjust the height to match aspect ratio if possible
            width = widthSpecSize;
            height = width * mVideoHeight / mVideoWidth;
            if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
                // couldn't match aspect ratio within the constraints
                height = heightSpecSize;
            }
        } else if (heightSpecMode == MeasureSpec.EXACTLY) {
            // only the height is fixed, adjust the width to match aspect ratio if possible
            height = heightSpecSize;
            width = height * mVideoWidth / mVideoHeight;
            if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
                // couldn't match aspect ratio within the constraints
                width = widthSpecSize;
            }
        } else {
            // neither the width nor the height are fixed, try to use actual video size
            width = mVideoWidth;
            height = mVideoHeight;
            if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
                // too tall, decrease both width and height
                height = heightSpecSize;
                width = height * mVideoWidth / mVideoHeight;
            }
            if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
                // too wide, decrease both width and height
                width = widthSpecSize;
                height = width * mVideoHeight / mVideoWidth;
            }
        }
    } else {
        // no size yet, just adopt the given spec sizes
    }
    setMeasuredDimension(width, height);
}
复制代码

おすすめ

転載: juejin.im/post/7085243234523283464