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

Picture in Picture support ? #380

Closed
Sach-SPF opened this issue Feb 3, 2020 · 5 comments
Closed

Picture in Picture support ? #380

Sach-SPF opened this issue Feb 3, 2020 · 5 comments

Comments

@Sach-SPF
Copy link

Sach-SPF commented Feb 3, 2020

has anyone integrated PIP in iOS/Android with opentok ? Just like WhatsApp...I have a requirement to keep the session active even if the user killed the app(swipe up) being a Publisher...

Any reference or suggestion would be really great

@sunweiyang
Copy link

I have an open issue on this topic (#172); I currently have my own native implementation of PIP for my own app.

@Sach-SPF
Copy link
Author

Sach-SPF commented Feb 8, 2020

I have an open issue on this topic (#172); I currently have my own native implementation of PIP for my own app.

Can you guide me or help me with some example or approach to accomplish this? Please help

@sunweiyang
Copy link

I created a React Native Android native module based on their docs:
https://facebook.github.io/react-native/docs/native-modules-android

Note that I made this a while ago, so the above docs may show you a better/more recommended way, but my current solution (shown below) still works.

I called my module PipModule. In my MainApplication.java, I add this package to the getPackages() method:

        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          packages.add(new PipPackage());  // Add this line
          return packages;
        }

I created a PipModule.java file in the same directory as MainApplication.java:

package com.myapp;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class PipModule extends ReactContextBaseJavaModule {
    public static boolean inPipMode = false;

    public PipModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "PipModule";
    }

    @ReactMethod
    public void setPipMode(boolean isPipMode) {
        inPipMode = isPipMode;
        return;
    }

}

And also a PipPackage.java file, in the same directory:

package com.myapp;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class PipPackage implements ReactPackage {

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }

  @Override
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();

    modules.add(new PipModule(reactContext));

    return modules;
  }

}

I can then use this native module in my JavaScript code, first by importing a few things from react-native: AppState to know backgrounded/foregrounded state, NativeModules to access my PipModule, and Platform so that I can target Android

import {
  ...
  AppState,
  NativeModules,
  Platform,
  ...
} from "react-native";

And then in my OpenTok chat screen component, I have these for componentDidMount() and componentWillUnmount():

  componentDidMount() {
    ...
    AppState.addEventListener("change", this._handleAppStateChange);
    if (Platform.OS === "android") {
      NativeModules.PipModule.setPipMode(true);
    }
    ...
  }
  componentWillUnmount() {
    ...
    AppState.removeEventListener("change", this._handleAppStateChange);
    if (Platform.OS === "android") {
      NativeModules.PipModule.setPipMode(false);
    }
    ...
  }

I define my _handleAppStateChange() method to save to state whether or not the app is backgrounded:

_handleAppStateChange = newAppState => {
  if (this.props.appState !== newAppState) {
      this.setState({appState: newAppState});
  }
}

The final thing to do is to change my subscriber's width and height when backgrounded, so that it fits in the PIP window (optionally you can also shrink your publisher so that it's out of the way, but in my case it wasn't necessary):

  render() {
    ...
    const isPipMode =
      this.state.appState === "background" && Platform.OS === "android";
    const normalWidth = SOME_INT
    const normalHeight = SOME_OTHER_INT
    const pipWidth = ANOTHER_INT
    const pipHeight = YET_ANOTHER_INT
    ...
    return (
      ...
              <OTSubscriber
                ...
                style={{
                  width: isPipMode ? pipWidth : normalWidth,
                  height: isPipMode ? pipHeight : normalHeight,
                  alignSelf: "center"
                }}
                ...
              />
      ...
    )
  }

@manikandana2z
Copy link

manikandana2z commented Jan 7, 2021

Hi sunweiyang,

 I am Manikandan. Currently, I am working in PIP mode - OpenTok. I have followed your code. But, PIP is not working for me when I have moved to Home Screen of my phone. Can you guide me?

@abdulajet
Copy link
Contributor

Thanks @sunweiyang

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants