Androidでちょっとした動画を再生したいと言われたので10分で対応してみる

# はじめに
Androidアプリにてふとした要件で動画を再生してほしいと言われたことはありませんか。
ビルトインで動画ファイル内包するのもなぁという思いもありつつあまり手間もかけたくない...
そんな時にあまり手間をかけずに実現するソリューションをご紹介しようと思います！

フォーカスしませんがその他の手段もまとめていますのでご活用いただければ嬉しいです。

今回作るアプリ
(みんな大好きbig buck bunnyです)
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782957/fb98bbf6-c01f-89bb-4d68-106704fbba5b.png"/>

# 全体の流れ
1. 動画ファイルをgoogle driveにアップロードする
2. google driveからリンクを取得
3. composeとexoplayerでgoogle driveの動画を再生する


## 動画リンクの用意
今回はサクッと試したいということで動画ストレージとしてgoogle driveを利用します。

1. google driveに動画をアップロードし、共有リンクを発行します。
(公開設定を「リンクを知っている人全員」にする必要があります。)

2. 以下のように共有リンクを変更して動画ファイルへのリンクを取得する。
    ```
    共有リンク: https://drive.google.com/file/d/<ファイルID>/view?usp=sharing
             ↓↓↓
    動画リンク: https://drive.google.com/open?id=<ファイルID>
    ```

## compose と exoplayerでプレイヤーの実装
動画ファイルへのリンクさえ用意できればあとは出回っているサンプル通りにexoplayerを実装するだけです。

manifest対応
```xml: AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
```

最新バージョンは[こちら](https://github.com/androidx/media)参照ください。
```toml:libs.versions.toml
media3 = "1.4.0-alpha01"

androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "media3" }
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3" }
androidx-media3-dash = { module = "androidx.media3:media3-exoplayer-dash", version.ref = "media3" }
```

```kotlin:
@Composable
fun VideoPlayer(modifier: Modifier) {
  val context = LocalContext.current
  val exoPlayer = remember {
    ExoPlayer.Builder(context).build().apply {
      playWhenReady = true
      setMediaItem(MediaItem.fromUri("google drive 動画ファイルへのリンク"))
      prepare()
    }
  }

  AndroidView(
    modifier = modifier
      .fillMaxWidth()
      .aspectRatio(16f / 9f),
    factory = {
      PlayerView(it).apply {
        player = exoPlayer
      }
    },
  )

  // イベントに合わせてexoplayer.release()など...
  LifecycleEventEffect(Lifecycle.Event.ON_PAUSE) {
    exoPlayer.pause()
  }
  LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
    exoPlayer.play()
  }
}
```

## ビルドして完了！
10分かからずにできたのではないでしょうか！
実際にはexoplayer周りは細かいカスタムが必要になることが多いのでここからが時間かかるというのが本音ですが...
以上が再生までの流れになります！

# その他の手段
今回は利用しておりませんが、その他の手段も紹介しておきます。

## android-youtube-playerを利用する
https://github.com/PierfrancescoSoffritti/android-youtube-player

後述するライブラリの後継となっているものです。google公式が出しているものではありませんが、star数3.4k(2024/06時点)と高い評価を得ています。
ただ最近更新されていないようなので、プロダクトで利用する場合は慎重に議論する必要がありそうです。

IFrame Player API をWebViewで動かしてYoutube動画を再生できるようにしています。
videoIdの指定だけで簡単に動画再生できます。
uiのカスタムなどもできますが、webViewなので一定の使いづらさはありそうです。

```java:
// READMEより
YouTubePlayerView youTubePlayerView = findViewById(R.id.youtube_player_view);
getLifecycle().addObserver(youTubePlayerView);

youTubePlayerView.addYouTubePlayerListener(new AbstractYouTubePlayerListener() {
  @Override
  public void onReady(@NonNull YouTubePlayer youTubePlayer) {
    String videoId = "S0Q4gqBUs7c";
    youTubePlayer.loadVideo(videoId, 0);
  }
});
```

現状Google側が公開しているYoutubeの再生手段はiFrameを使ってwebViewで表示するしかないので、
このライブラリを利用するかこのライブラリを参考にwebViewを自作するかというやり方になりそうです。

## youtubeなどからm3u8を取得しexoplayerに流す
exoplayerはHlsMediaSourceなどを使うことでもちろんストリーミング再生することができるためm3u8ファイルなどを準備できれば動画再生できます。

ただし公式docsではyoutube動画を直接exoplayerで再生することはできないと公言しています。
そのためyoutubeからm3u8ファイルを引っこ抜いてこの方法を取ることは裏技的なものなので安易に選択すべきではありません。 (youtubeから取れるかも未検証です。)
今記事で取り上げたのは安易にこの手法を試して欲しくないという思いからです。 (お試しする場合は自己責任でお試しください。)
https://developer.android.com/media/media3/exoplayer/troubleshooting#can-i-play-youtube-videos-directly-with-exoplayer

> Can I play YouTube videos directly with ExoPlayer?
No, ExoPlayer cannot play videos from YouTube, such as URLs of the form https://www.youtube.com/watch?v=.... Instead, you should use the YouTube IFrame Player API, which is the official way to play YouTube videos on Android.

## YouTube Android Player APIを利用する(非推奨なので注意)
現在このライブラリはセキュリティ的な理由もあり非推奨となっているため利用しないことを強くお勧めします。
https://developers.google.com/youtube/android/player?hl=ja

ちょこちょこ見かけますが`YouTubeBaseActivity`などを利用しているサンプルコードは注意が必要です。

# 参考
https://github.com/android/codelab-exoplayer-intro/tree/main
https://qiita.com/rot-z/items/299ac40361690c51ce1d