Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Créer votre player Netflix avec Exoplayer (codelabs) #1016

Merged
merged 1 commit into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions _tutorials/fr/2019-08-30-kotlin-exoplayer/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
contentType: tutorial
lang: fr
date: '2019-08-30'
slug: kotlin-exoplayer
title: Créer votre player Netflix avec Exoplayer
excerpt: >-
Dans ce tutoriel nous allons créer un player android en Kotlin grâce à Exoplayer, pour pouvoir lire une vidéo locale mp4.
categories:
- architecture
authors:
- babas
keywords:
- android
- kotlin
steps:
- introduction
- creation-du-player
- creation-ui
- gestion-des-etats
---

116 changes: 116 additions & 0 deletions _tutorials/fr/2019-08-30-kotlin-exoplayer/steps/creation-du-player.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
contentType: tutorial-step
tutorial: kotlin-exoplayer
slug: creation-du-player
title: Création du Player
---
## Création du player Exoplayer :

### Prérequis :

Créez un fichier versions.gradle dans le répertoire de votre projet et listez vos dépendances en spécifiant leur version. N'oubliez pas d'y introduire la liste des versions que vous utiliserez dans vos dépendances.
Ici :

```java
ext {
exoPlayerVersion = '2.9.6'
}
```

Dans votre fichier build.gradle applicatif ajoutez en haut :

apply from: 'versions.gradle'

Enfin, ajoutez dans votre fichier build.gradle les dépendances à ExoPlayer :

```java
// exoplayer
implementation "com.google.android.exoplayer:exoplayer-core:$exoPlayerVersion"
implementation "com.google.android.exoplayer:exoplayer-ui:$exoPlayerVersion"
```

### En ce qui concerne le Player

Nous allons créer une classe Player. Cette classe va avoir un rôle de façade sur notre player ExoPlayer pour exécuter toutes nos actions type play, pause, instancier notre player, le configurer en fonction du flux d'entrée...

Pour commencer nous allons créer une variable privé de type SimpleExoPlayer et l'initialiser dans notre objet :

```java
class Player(val context: Context) {

private var player: SimpleExoPlayer = ExoPlayerFactory.newSimpleInstance(context)

}
```

À partir d'ici, nous avons notre player instancié. Maintenant il faut lui permettre de lire des vidéos locales. Nous allons donc créer une méthode qui va lui permettre de décoder notre fichier video. ExoPlayer est capable de lire un nombre assez conséquent de formats vidéos différents, que ce soient des vidéos locales ou des streams live. Pour différencier ces types de flux d'entrées nous devons créer un fichier de type MediaSource, qui est le media final que nous passerons à notre player ExoPlayer pour qu'il le lise. Pour créer ce fichier, nous devons passer par une des factories ExoPlayer, qui différera en fonction du flux. À savoir qu'en entrée, la factory va demander une URI.

Ici j'ai choisi de lire un fichier MP4, format considéré comme standard par exoplayer :

```java
private fun buildMediaSource(uri: Uri): MediaSource {
val factorymediaSourceFactory: ExtractorMediaSource.Factory =
ExtractorMediaSource.Factory(
DefaultDataSourceFactory(
context,
Util.getUserAgent(context, "MyNetflix")
)
)
return factorymediaSourceFactory.createMediaSource(uri)
}
```

Nous avons notre player, notre MediaSource résultant de la transformation de notre URI. Mais il nous manque un dernier détail... Pour pouvoir s'afficher correctement, ExoPlayer a besoin qu'on lui fournisse une SurfaceView, custom view de la librairie Exoplayer sur laquelle il va pouvoir afficher son contenu.

Nous allons donc pour l'instant ajouter une méthode pour fournir à notre objet Player une surfaceView :

```java
fun setVideoSurface(surfaceview: SurfaceView) {
player.setVideoSurfaceView(surfaceview)
}
```

Enfin bien sûr, nous allons ajouter plusieurs actions, pour pouvoir tester notre super player par la suite.

Pour charger notre média :

```java
fun prepare(uri: Uri) {
player.prepare(buildMediaSource(uri), false, true);
}
```

Pour reset notre player :

```java
fun stop() {
player.stop(true)
player.seekToDefaultPosition()
}
```

Pour lancer la lecture :

```java
fun play() {
player.playWhenReady = true
}
```

Pour le mettre en pause :

```java
fun pause() {
player.playWhenReady = false
}
```

Et un getter sur son état en lecture ou pas :

```java
fun isPlaying() {
return player.playWhenReady
}
```

À savoir que pour indiquer que l'on veut jouer la vidéo de notre player, il faut modifier la valeur du boolean playWhenReady. ExoPlayer écoute cette valeur. Dès qu'elle est modifiée et s'il n'est pas en cours d'initialisation il lancera instantanément la vidéo. Sinon il attendra de finir son initialisation puis la lancera.
122 changes: 122 additions & 0 deletions _tutorials/fr/2019-08-30-kotlin-exoplayer/steps/creation-ui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
contentType: tutorial-step
tutorial: kotlin-exoplayer
slug: creation-ui
title: Création de l'UI
---

## Création de notre vue PlayerView :

Créez un fichier player_view.xml dans le dossier layout de votre projet.
Dans ce fichier nous allons ajouter une SurfaceView, réceptacle de notre player, et un bouton play/pause qui permettra de lancer/arrêter le flux :

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">

<SurfaceView
android:id="@+id/surface_view"
android:layout_width="400dp"
android:layout_height="300dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/play_pause_button"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/exo_controls_play"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```
Ensuite nous allons créer une classe PlayerView qui héritera de FrameLayout, dans laquelle on va définir différents comportements, notamment la gestion de l'état du bouton play/pause, son logo, et les actions que ce bouton va effectuer.

```java
class PlayerView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

init {
inflate(context, R.layout.player_view, this)
}
}
```

On va y initialiser notre PlayerManager :

```java
private lateinit var playerManager: PlayerManager

private fun initPlayer() {
playerManager = PlayerManager(context = context)
playerManager.setVideoSurface(surface_view)
playerManager.prepare(Uri.parse("file:/android_asset/example_video.mp4"))
}
```

Et dans notre bloc init, on va exécuter notre initPlayer puis définir un listener sur notre bouton pour modifier l'icône et ainsi nous permettre d'avoir un retour UX entre nos lectures et nos pauses :

À savoir que des ressources sont mises à disposition par la librairie pour avoir des images de contrôles ISO sur tout les players, les ressources exo_controls_play et exo_controls_pause sont donc accessibles sans avoir à ajouter d'icônes dans votre projet.

```java
init {
inflate(context, R.layout.player_view, this)

play_pause_button.setOnClickListener {
if (playerManager.isPlaying()) {
playerManager.pause()
play_pause_button.setBackgroundResource(R.drawable.exo_controls_play)
} else {
playerManager.play()
play_pause_button.setBackgroundResource(R.drawable.exo_controls_pause)
}
}
initPlayer()
}
```

### Ressources :

Niveau ressourcee, créez un dossier assets dans votre dossier main à coté des dossiers res et java et mettez y vos ressources vidéos.
Ainsi vous pourrez y accéder dans vos tests comme défini plus haut :

"file:/android_asset/example_video.mp4"

### Tests :

Afin de tester, créer une MainActivity. Dans son layout activity_main définissez un PlayerView comme bon vous semble niveau format :

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<com.example.mynetflix.PlayerView
android:id="@+id/player"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

Si tout s'aligne bien, vous pouvez exécuter votre code et lancer votre application !
Loading
Loading