Custom Video Player doesnt work on iphone.

Custom Code

I have built a custom widget that it is a custom video player with chewie, it works on Test Mode but not on iphone.

What have you tried so far?

Ask AI and check communities.

// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/backend/schema/structs/index.dart';
import '/backend/schema/enums/enums.dart';
import '/backend/supabase/supabase.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/custom_code/actions/index.dart'; // Imports custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:visibility_detector/visibility_detector.dart';

class ChewieVideoPlayer extends StatefulWidget {
  final String videoPath;
  final double width;
  final double height;

  ChewieVideoPlayer({
    required this.videoPath,
    required this.width,
    required this.height,
  });

  @override
  _ChewieVideoPlayerState createState() => _ChewieVideoPlayerState();
}

class _ChewieVideoPlayerState extends State<ChewieVideoPlayer> {
  VideoPlayerController? _videoController;
  ChewieController? _chewieController;
  bool _isLoading = true;
  bool _currentlyVisible = false;
  bool _videoInitialized = false;
  GlobalKey videoKey = GlobalKey();
  static List<GlobalKey> videoKeys = [];
  static List<VideoPlayerController> allVideoControllers =
      []; // Lista de todos los controladores
  static VideoPlayerController?
      _currentlyPlayingController; // Video actualmente en reproducción
  Future<void>? _initializationFuture;

  @override
  void initState() {
    super.initState();
    _loadVideoUrl();
    _ChewieVideoPlayerState.videoKeys.add(videoKey);
  }

  Future<void> _loadVideoUrl() async {
    if (!_videoInitialized) {
      try {
        String videoUrl = await FirebaseStorage.instance
            .ref(widget.videoPath)
            .getDownloadURL();
        if (mounted) {
          _initializationFuture = _initializePlayer(videoUrl);
        }
      } catch (e) {
        debugPrint("Error loading video: $e");
        if (mounted) {
          setState(() => _isLoading = false);
        }
      }
    }
  }

  Future<void> _initializePlayer(String videoUrl) async {
    try {
      _videoController = VideoPlayerController.network(videoUrl);
      await _videoController?.initialize();
      if (!mounted) return;

      allVideoControllers
          .add(_videoController!); // Agregar el controlador a la lista

      _chewieController = ChewieController(
        videoPlayerController: _videoController!,
        autoPlay: false,
        looping: true,
        showControls: false,
        aspectRatio: _videoController!.value.aspectRatio,
      );

      setState(() {
        _isLoading = false;
        _videoInitialized = true;
      });

      _videoController?.addListener(() {
        if (_videoController?.value.hasError ?? false) {
          debugPrint(
              "Video error: ${_videoController?.value.errorDescription}");
        }
      });

      // Reproducir automáticamente si está visible
      if (_currentlyVisible) {
        _playVideo();
      }
    } catch (e) {
      debugPrint("Error initializing player: $e");
      if (mounted) {
        setState(() => _isLoading = false);
      }
    }
  }

  void _onVisibilityChanged(VisibilityInfo info) {
    bool isVisible = info.visibleFraction > 0.9; // Umbral de 0.5 para pausa
    if (_currentlyVisible != isVisible) {
      setState(() {
        _currentlyVisible = isVisible;
      });

      // Si el video está visible y ha sido inicializado, reproducirlo
      if (_videoInitialized) {
        if (_currentlyVisible) {
          _playVideo();
        } else {
          _videoController?.pause();
        }
      }
    }
  }

  void _playVideo() {
    if (_currentlyPlayingController != null &&
        _currentlyPlayingController != _videoController &&
        _currentlyPlayingController!.value.isPlaying) {
      _currentlyPlayingController?.pause();
    }
    _currentlyPlayingController = _videoController;
    _videoController?.play();
  }

  void _togglePlayback() {
    setState(() {
      if (_videoController?.value.isPlaying ?? false) {
        _videoController?.pause();
      } else {
        _playVideo();
      }
    });
  }

  @override
  void dispose() {
    if (_initializationFuture != null) {
      _initializationFuture = null;
    }
    allVideoControllers
        .remove(_videoController); // Remover el controlador al hacer dispose
    if (_videoController?.value.isPlaying ?? false) {
      _videoController?.pause(); // Pausa al hacer dispose
    }
    _videoController?.dispose();
    _chewieController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    double screenWidth = MediaQuery.of(context).size.width;
    double videoAspectRatio = _videoController?.value.aspectRatio ?? 16 / 9;
    double videoHeight = screenWidth / videoAspectRatio;

    return VisibilityDetector(
      key: Key(widget.videoPath),
      onVisibilityChanged: _onVisibilityChanged,
      child: GestureDetector(
        onTap: _togglePlayback,
        child: Center(
          child: SizedBox(
            key: videoKey,
            width: screenWidth,
            height: videoHeight,
            child: _isLoading
                ? const Center(child: CircularProgressIndicator())
                : (_chewieController != null
                    ? ClipRRect(
                        borderRadius: BorderRadius.zero,
                        child: FittedBox(
                          fit: BoxFit.cover,
                          child: SizedBox(
                            width: screenWidth,
                            height: videoHeight,
                            child: Chewie(controller: _chewieController!),
                          ),
                        ),
                      )
                    : const SizedBox.shrink()),
          ),
        ),
      ),
    );
  }
}
Did you check FlutterFlow's Documentation for this topic?
No
1