Flutter meets Video

von

Flutter meets Video

In diesem Blogpost möchte ich kurz vorstellen, wie einfach die Einbindung von Videos in Flutter umgesetzt werden kann. Dabei betrachten wir zwei aufeinander aufbauende Plugins, gefolgt von einem kleinen Tipp, wie die Nutzererfahrung ohne Unterbrechung stattfindet.

Video Player

Videos lassen sich dank des offiziellen video_player Plugins leicht in vorhandene Flutter Apps integrieren. Als Quelle können lokale Dateien, Assets sowie das Netzwerk dienen. Im Fall des Letzten buffert das Plugin die eingehenden Daten automatisch, sofern der Server das Video für die Plattformen korrekt bereitstellt.

Als Erstes müssen die Berechtigungen für iOS und Android entsprechend gesetzt werden.

Für iOS in der Info.plist (unter /ios/Runner/Info.plist) das folgende Key/Value Pair ergänzen:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

Für Android hingegen, falls nicht schon vorhanden, die Internet-Berechtigung im Android Manifest (unter android/app/src/main/AndroidManifest.xml) setzen:

<uses-permission android:name="android.permission.INTERNET"/>

Damit kann die Integration beginnen. Als erstes definieren wir einen Controller, der die Video-Quelle anzieht und warten auf dessen Initialisierung. Der Aufruf von setState dient dazu, das erste Bild des Videos als Vorschau darzustellen, nachdem die Initialisierung abgeschlossen ist. In diesem Fall laden wir ein mp4-Video aus dem Internet:

late VideoPlayerController _controller;

@override
void initState() {
  super.initState();
  _controller = VideoPlayerController.network(
      'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4')
    ..initialize().then((_) {
      setState(() {});
    });
}

Nun kann der Controller an das Video Player Plugin übergeben werden. Um eine Möglichkeit zum Starten und Stoppen des Videos müssen wir uns aber noch selbst kümmern. Dafür verwenden wir in diesem Beispiel einen einfachen FloatingActionButton, welcher den Controller je nach Status startet oder stoppt und ein passendes Icon dafür anzeigt:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Flutter meets Video'),
    ),
    body: Center(
      child: _controller.value.isInitialized
          ? AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: VideoPlayer(_controller),
            )
          : CircularProgressIndicator(),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () {
        setState(() {
          _controller.value.isPlaying
              ? _controller.pause()
              : _controller.play();
        });
      },
      child: Icon(
        _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
      ),
    ),
  );
}

Das Ergebnis sieht wie folgt aus:

Die aktuelle Implementierung unterscheidet nicht zwischen Cupertino und Material Design, genauso wenig existiert schon die Möglichkeit, in den Vollbildmodus zu wechseln oder andere gängige Optionen, wie die Möglichkeit im Video zu Springen. Natürlich lässt sich das manuell umsetzen, aber hierfür gibt es ein weiteres Plugin, das auf dem Video-Player aufbaut und für die mobilen Varianten sowie Web passende UI-Elemente bereitstellt.

Chewie

Neben den Plattform konformen UI-Elementen stellt Chewie weitere Funktionen wie Abspielgeschwindigkeit oder Untertitel bereit, auf die wir hier aber nicht genauer eingehen.

Sobald Chewie importiert ist, müssen wir den vorhandenen Code nur leicht anpassen. In der initState Methode wird neben dem VideoController ein ChewieContoller erzeugt, an dem diverse Optionen direkt definiert werden können. Der wichtigste Teil ist die Zuweisung des Contollers:

late VideoPlayerController _controller;
late ChewieController _chewieController;

@override
void initState() {
  super.initState();
  _controller = VideoPlayerController.network(
      'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4')
    ..initialize().then((_) {
      _chewieController = ChewieController(
        videoPlayerController: _controller,
        autoPlay: false,
        looping: false,
      );
      setState(() {});
    });
}

Da wir uns jetzt nicht mehr selbst um die UI-Elente kümmern müssen, vereinfacht sich der Code im zweiten Bereich deutlich. Hier wird nur noch dem Chewie Widget der entsprechende Controller übergeben und angezeigt, sobald die Initialisierung abgeschlossen ist:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Flutter meets Video'),
    ),
    body: Center(
      child: _controller.value.isInitialized
          ? SafeArea(
              child: Chewie(
                controller: _chewieController,
              ),
            )
          : CircularProgressIndicator(),
    ),
  );
}

Das ist alles, was man benötigt, um Videos in Flutter einzubinden.

Bonus Tipp

Bei längeren Videos kann es passieren, dass das Gerät in den Ruhemodus geht und die Wiedergabe unterbricht. Eine Lösung hierfür bietet das Plugin Wakelock, das, wie der Name schon erahnen lässt, die automatische Sperre unterbindet.

Dieses Plugin braucht keine Weiteren Permissions und kann einfach bei der Navigation zum Video-Screen, in der initState Methode, aktiviert werden:

@override
void initState() {
  super.initState();
  Wakelock.enable();
  _controller = …
}

Man sollte nur nicht vergessen, Wakelock nach Verlassen des Screens oder nach beenden des Videos wieder zu deaktivieren:

@override
void dispose() {
  super.dispose();
  Wakelock.disable();
  _chewieController.dispose();
  _controller.dispose();
}

Fazit

Ich hoffe dieser Blogpost hat gezeigt, wie einfach sich Videos in Flutter dank der verfügbaren Plugins integrieren lassen. Mit nur wenig Aufwand lässt sich eine Plattform spezifische Lösung für Android und iOS umsetzen, welche sämtliche Interaktion bereitstellt, die Nutzer erwarten. Und mittels Wakelock kann gewährleistet werden, dass das Nutzungserlebnis ohne Unterbrechung stattfindet.


Kategorien: DartFlutter

Zurück