ExoPlayer Okhttp Extentionで ExoPlayerのネットワークをカスタマイズする

# ExoPlayer Okhttp Extentionとは
[ExoPlayer](https://github.com/google/ExoPlayer)はAndroidで動画・音声を再生するフレームワークです。
ExoPlayerではたくさんの拡張ライブラリが用意されており、その中のひとつに[Okhttp Extention](https://github.com/google/ExoPlayer/tree/release-v2/extensions/okhttp)があります。
Okhttp Extentionを使用すれば、[OkHttp](https://square.github.io/okhttp/)を使ってExoPlayerのネットワークをカスタマイズ出来ます。

具体的には、**ExoPlayerが受け取るレスポンスデータを書きかえたり、ステータスコードを書き換えたり... Okhttpで出来ること全てが可能です**。
ただ、**Httpタイムアウト時間・リクエストヘッダのカスタマイズ・ネットワークイベントなどはコアライブラリのみで対応可能**です。

# 導入
gradleのdependencyにokhttp extentionを追加します。extentionのバージョンはExoPlayer本体のバージョンと一致させます。

```gradle
def ver_exoplayer = 'x.x.x'
implementation "com.google.android.exoplayer:exoplayer-core:$ver_exoplayer"
implementation "com.google.android.exoplayer:extension-okhttp:$ver_exoplayer"
```

# 使い方
`DefaultDataSource`, `DefaultDataSourceFactory`の代わりに`OkHttpDataSource` `OkHttpDataSourceFactory`を用います。
例えば以下の例ではサーバー上の動画ファイルを再生・リクエスト時にログします。

```kotlin

val client = OkHttpClient().newBuilder().addNetworkInterceptor(object : Interceptor {
        override fun intercept(chain: Interceptor.Chain): Response {
             Log.d("LOG", "REQUEST INTERCEPTED")
             return chain.proceed(chain.request())
        }
}).build()
val okHttpDataSourceFactory = OkHttpDataSourceFactory(client, "USER_AGENT")
val mediaSource = ProgressiveMediaSource.Factory(okHttpDataSourceFactory)
        .createMediaSource("MP4_URL".toUri())
player.prepare(mediaSource)
player.playWhenReady = true
```

OkHttpDataSource/OkHttpDataSourceFactoryにはカスタマイズした[Okhttp.Call](https://square.github.io/okhttp/4.x/okhttp/okhttp3/-call/)を渡すことができるので、この部分で自由にカスタマイズできるという訳です。

# リクエストヘッダ・タイムアウト時間をカスタムする場合はOkhttp Extentionは不要
リクエストヘッダ・タイムアウト時間・リダイレクトなどの設定なら、コアライブラリに含まれる[DefaultHttpDataSourceFactory](https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.html)で対応可能です。
Okhttp Extentionを使用せずに済みます。

##### 例

```kotlin

val factory = DefaultHttpDataSourceFactory(
  userAgent,
  connectTimeout,
  readTimeout, 
  allowCrossProtocolRedirects/*HTTP<=>HTTPS間のリダイレクトを許容するかどうか*/
)
factory.defaultRequestProperties.set("headerName", "headerValue")
val mediaSource = ProgressiveMediaSource.Factory(factory).createMediaSource("REMOTE_URL".toUri())
player.prepare(mediaSource)
player.playWhenReady = true
```

# ネットワークイベントを作成する場合はOkhttp Extentionは不要

ダウンロードの進捗やリクエストの各パラメータを知りたいなら、コアライブラリの[TransferListener](https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/upstream/TransferListener.html)が便利です。
Okhttp Extentionを使用せずに済みます。

##### 例

```kotlin

// dataSpecからリクエストパラメータやストリーム中のポジションを取得できます
// requestパラメータ:
//   dataSpec?.httpBody
//   dataSpec?.httpRequestHeaders
//   dataSpec?.httpMethod
// ストリーム中のポジション:
//   dataSpec?.position
//   dataSpec?.absoluteStreamPosition
val transferListener = object : TransferListener {
            override fun onTransferInitializing(
                source: DataSource?,
                dataSpec: DataSpec?,
                isNetwork: Boolean
            ) {
                
            }

            override fun onTransferStart(
                source: DataSource?,
                dataSpec: DataSpec?,
                isNetwork: Boolean
            ) {
                
            }

            override fun onTransferEnd(
                source: DataSource?,
                dataSpec: DataSpec?,
                isNetwork: Boolean
            ) {
                
            }

            override fun onBytesTransferred(
                source: DataSource?,
                dataSpec: DataSpec?,
                isNetwork: Boolean,
                bytesTransferred: Int
            ) {
                
            }
        }

val factory = DefaultDataSourceFactory(getApplication(), userAgent, transferListener)
val mediaSource = ProgressiveMediaSource.Factory(factory).createMediaSource("REMOTE_URL".toUri())
player.prepare(mediaSource)
player.playWhenReady = true
```

# さいごに
Okhttp Extentionは自由度が高く何でもできますが、基本的なことならコアライブラリのみで実装可能です。
レスポンスデータそのもの書きかえたい時など、使用する場面は割と限られてくるかと思います。