fluttercommunity / chewie

The video player for Flutter with a heart of gold
MIT License
1.92k stars 989 forks source link

app crash when change playback speed when screen is not in full screen #766

Open Shubh-Vyas-ey opened 1 year ago

Shubh-Vyas-ey commented 1 year ago

app crash when change playback speed when screen is not in full screen

class VideoPlayerScreen extends StatefulWidget { final String vmID; final int totlaSecondShouldVIdeoPlay; Map<String, dynamic> details;

VideoPlayerScreen( {Key? key, required this.vmID, required this.details, required this.totlaSecondShouldVIdeoPlay}) : super(key: key);

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

class _VideoPlayerScreenState extends State with WidgetsBindingObserver { final BaseAPiServices _apiServices = NetworkApiService(); VideoPlayerController? _videoPlayerController; ChewieController? _chewieController; int _playedSeconds = 0; String videoUrl = ""; DateTime? _playStartTime; Duration? _totalPlayedDuration; bool _isVideoPlaying = false; int _lastPlayedSeconds = 0;

@override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); callApiOrNot(); }

sendDuration({required String duration}) { Map<String, dynamic> body = widget.details; body["duration"] = duration; if (kDebugMode) { print("json body $body"); } // return; String api = API.sendDuration; _apiServices.httpPost( api: api, parameters: body, showLoader: false, success: (sucess) { if (kDebugMode) { print("send done $sucess"); } }, failure: (error) { if (kDebugMode) { print("error error $error"); } }); }

// Pause the video playback void pauseVideo() { _videoPlayerController?.pause(); }

// Resume the video playback void resumeVideo() { _videoPlayerController?.play(); }

@override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); print("changee"); if (state == AppLifecycleState.paused) { if (_videoPlayerController != null) { pauseVideo(); sendDuration(duration: _totalPlayedDuration!.inSeconds.toString()); setState(() { _playedSeconds = 0; _lastPlayedSeconds = 0; }); return; } } else if (state == AppLifecycleState.resumed) { resumeVideo(); return; } else if (state == AppLifecycleState.detached) { if (_videoPlayerController != null) { pauseVideo(); sendDuration(duration: _totalPlayedDuration!.inSeconds.toString()); setState(() { _playedSeconds = 0; _lastPlayedSeconds = 0; }); return; } } }

// Determine whether to call the API or use cached video URL void callApiOrNot() async { try { String lastApiCall = await Pref.getTimeOfAPICall(key: widget.vmID); String videoUrlData = await Pref.getVideoUrl(key: widget.vmID); DateTime dateTime = DateTime.parse(lastApiCall); Duration difference = DateTime.now().difference(dateTime); if (difference.inHours > 1) { getStreamUrlFromVimeo(vmID: widget.vmID); } else { setState(() { videoUrl = videoUrlData; }); setVideoData(videoUrlData: videoUrl); } } catch (e) { getStreamUrlFromVimeo(vmID: widget.vmID); } }

// Fetch the video stream URL from Vimeo API void getStreamUrlFromVimeo({required String vmID}) async { await _apiServices.httpGet( api: "${API.getUrlFromVimeo}$vmID/config", showLoader: false, success: (sucess) async { String inString = json.encode(sucess); log("inString $inString"); final getUrlFromVimeo = getUrlFromVimeoFromJson(inString); setState(() { videoUrl = getUrlFromVimeo.request.files.hls.cdns.akfireInterconnectQuic.url; }); await Pref.setVideoUrl(value: videoUrl, key: widget.vmID); await Pref.setTimeOfAPICall( key: widget.vmID, value: DateTime.now().toString()); setVideoData(videoUrlData: videoUrl); }, failure: (error) { Utils.flushBarErrorMessage( message: "Something Went Wrong while playing Video", context: context, ); }, ); }

// Set the video data and initialize controllers void setVideoData({required String videoUrlData}) { _videoPlayerController = VideoPlayerController.network(videoUrlData); _chewieController = ChewieController( videoPlayerController: _videoPlayerController!, aspectRatio: 24 / 12, // Adjust according to your video aspect ratio autoPlay: true, showControls: true, zoomAndPan: true, allowFullScreen: true, fullScreenByDefault: true, allowPlaybackSpeedChanging: false, looping: false, errorBuilder: (context, errorMessage) { return Center( child: Text( errorMessage, style: const TextStyle(color: Colors.white), ), ); }, ); _videoPlayerController!.addListener(_videoPlayerListener); }

void _videoPlayerListener() { if (_videoPlayerController!.value.isPlaying) { if (!_isVideoPlaying) { setState(() { _playStartTime = DateTime.now(); _totalPlayedDuration = Duration(seconds: _lastPlayedSeconds); _isVideoPlaying = true; }); } else { final currentTime = DateTime.now(); final playedDuration = currentTime.difference(_playStartTime!); _totalPlayedDuration = _totalPlayedDuration! + playedDuration; _playStartTime = currentTime; setState(() { _playedSeconds = _totalPlayedDuration!.inSeconds; });

    // Check if the video has played for the desired duration
    if (_totalPlayedDuration!.inSeconds >=
        widget.totlaSecondShouldVIdeoPlay) {
      // Pause the video
      pauseVideo();

      // Exit full screen
      if (_chewieController!.isFullScreen) {
        _chewieController!.exitFullScreen();
      }

      // Call the API to send duration
      sendDuration(duration: _totalPlayedDuration!.inSeconds.toString());
      showDialog(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return SubscriptionDialog(
            title: "Duration Completed",
            subtitle:
                "Your Duration for this video is completed Thanks for be with us",
          );
        },
      );
      // Pop from the video player screen
      Navigator.of(context).pop();
    }
  }
} else {
  if (_isVideoPlaying) {
    setState(() {
      _isVideoPlaying = false;
      _lastPlayedSeconds = _totalPlayedDuration!.inSeconds;
    });
  }
}

}

@override void dispose() { WidgetsBinding.instance.removeObserver(this); _videoPlayerController!.dispose(); _chewieController!.dispose(); super.dispose(); }

@override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { if (_chewieController!.isFullScreen) { _chewieController!.exitFullScreen(); return false; } if (!_chewieController!.isFullScreen) { sendDuration(duration: _totalPlayedDuration!.inSeconds.toString()); setState(() { _playedSeconds = 0; _lastPlayedSeconds = 0; }); return true; } return true; }, child: SafeArea( child: Scaffold( body: Container( color: Colors.white, child: Center( child: (_chewieController != null && _videoPlayerController != null && videoUrl.isNotEmpty) ? Container( color: AppColors.blackColor, child: Chewie( controller: _chewieController!, ), ) : const Text("Hold the Coffe ☕ Your Video 🎥 is on the Way"), ), ), ), ), ); } }

Trung15010802 commented 11 months ago

I have the same issue. Can anyone help me please?

Isra0210 commented 10 months ago

I had the same problem, I just set the controller's allowPlaybackSpeedChanging flag to false and it worked (but I can't say why).