TheWidlarzGroup / react-native-video

A <Video /> component for react-native
https://docs.thewidlarzgroup.com/react-native-video/
MIT License
7.21k stars 2.9k forks source link

Android - Video does not pause when app backgrounded #2898

Closed jemise111 closed 2 years ago

jemise111 commented 2 years ago

Bug

(Android only) Putting an app in the background with a video that is currently playing will not pause the video despite passing playInBackground={false}.

I tried to debug a little and suspect that the React Native Lifecycle event callbacks aren't being triggered. I added a breakpoint here and it never gets called when backgrounding the app.

Platform

Environment info

info Fetching system and libraries information...
System:
    OS: macOS 12.6
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 738.09 MB / 16.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 14.18.3 - /var/folders/_x/r81bfwqj16lfwkj7k1f49npm0000gn/T/yarn--1666636181620-0.5504628423052143/node
    Yarn: 1.22.18 - /var/folders/_x/r81bfwqj16lfwkj7k1f49npm0000gn/T/yarn--1666636181620-0.5504628423052143/yarn
    npm: 6.14.15 - ~/.nvm/versions/node/v14.18.3/bin/npm
    Watchman: 2022.03.21.00 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.11.3 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.4, iOS 16.0, macOS 12.3, tvOS 16.0, watchOS 9.0
    Android SDK:
      API Levels: 23, 28, 29, 30, 31, 33
      Build Tools: 28.0.3, 29.0.2, 29.0.3, 30.0.2, 30.0.3, 31.0.0, 33.0.0
      System Images: android-28 | Google APIs Intel x86 Atom, android-29 | Intel x86 Atom_64, android-29 | Google APIs Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: 2020.3 AI-203.7717.56.2031.7621141
    Xcode: 14.0.1/14A400 - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.11 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.2 => 17.0.2
    react-native: 0.66.4 => 0.66.4
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found
✨  Done in 6.26s.

Library version: 6.0.0-alpha.3

Steps To Reproduce

  1. Start playing a video (.mp4 or .m3u8)
  2. Press the home button or app switcher on an Android device
  3. Observe video/audio continues to play ...

Expected behaviour

  1. Start playing a video (.mp4 or .m3u8)
  2. Press the home button or app switcher on an Android device
  3. If the playInBackground prop is set to false (which is the default) video should pause until app is resumed

Reproducible sample code

Should be reproducible with any instance of Video. e.g.

<VideoPlayer
  source={{
    uri: <any_mp4_url>,
    type: "video/mp4",
  }}
  playInBackground={false}
/>
freeboub commented 2 years ago

Which version of react-native do you use ? Notive that on my working fork, I fully reimplement the lifecycle management. Normally video should not stop when app is paused... I need to find time to backport this change! Edit: and yes, the breakpoint to correctly placed

jemise111 commented 2 years ago

Hey @freeboub react native version is 0.66.4

Normally video should not stop when app is paused...

That's fine but I would think the playInBackground prop can control this behavior

Great to hear you have it working on a fork, hopefully it can make it in the main branch here too. I appreciate all of the work on this!

freeboub commented 2 years ago

I check on basic sample in the repo, I don't reproduce the issue ... even if I force playInBackground={false} but this should be the default behavior Can it be an issue with react / react integration ?

jemise111 commented 2 years ago

Wow @freeboub you're right. I created a fresh react native app and tried to reproduce this and I could not. I supposed it's an issue with an older version of react-native. Thanks for the suggestion!

nikonhub commented 1 year ago

I had the same issue, onHostResume/Pause methods not called. Fixed it by refactoring a bit.

I can't understand why though.

Instead of ReactExoplayerView implementing LifecycleEventListener

class ReactExoplayerView implements LifecycleEventListener {
    ....
    themedReactContext.addLifecycleEventListener(this);

    ....
    @Override
    public void onHostResume() {

Create a new instance of lifecyclelistener and add it.

      LifecycleEventListener lifecycleListener = new LifecycleEventListener() {
            @Override
            public void onHostResume() {
                if (!playInBackground || !isInBackground) {
                    setPlayWhenReady(!isPaused);
                }
                isInBackground = false;
            }

            @Override
            public void onHostPause() {
                isInBackground = true;
                if (playInBackground) {
                    return;
                }
                setPlayWhenReady(false);
            }

            @Override
            public void onHostDestroy() {
                stopPlayback();
                themedReactContext.removeLifecycleEventListener(this);
            }
        };
        themedReactContext.addLifecycleEventListener(lifecycleListener);