Skip to content

Commit

Permalink
Picture-in-Picture Fix (#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthur Geron authored Aug 29, 2023
1 parent 7d594fd commit 9ce7e60
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.amazonaws.ivs.reactnative.player

import android.app.Activity
import android.app.PictureInPictureParams
import android.content.pm.PackageManager
import android.net.Uri
import android.widget.FrameLayout
Expand All @@ -14,10 +16,6 @@ import com.facebook.react.uimanager.events.RCTEventEmitter
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.concurrent.timerTask
import android.app.PictureInPictureParams
import android.app.Activity
import androidx.annotation.RequiresApi


class AmazonIvsView(private val context: ThemedReactContext) : FrameLayout(context), LifecycleEventListener {
private var playerView: PlayerView? = null
Expand All @@ -30,6 +28,8 @@ class AmazonIvsView(private val context: ThemedReactContext) : FrameLayout(conte
private var lastBitrate: Long? = null
private var lastDuration: Long? = null
private var finishedLoading: Boolean = false
private var pipEnabled: Boolean = false
private var isInBackground: Boolean = false

enum class Events(private val mName: String) {
STATE_CHANGED("onPlayerStateChange"),
Expand Down Expand Up @@ -200,6 +200,11 @@ class AmazonIvsView(private val context: ThemedReactContext) : FrameLayout(conte
player?.isAutoQualityMode = autoQualityMode
}

fun setPipEnabled(_pipEnabled: Boolean) {
pipEnabled = _pipEnabled
if (!pipEnabled) togglePip()
}

fun onTextCue(cue: TextCue) {
val reactContext = context as ReactContext

Expand Down Expand Up @@ -429,29 +434,43 @@ class AmazonIvsView(private val context: ThemedReactContext) : FrameLayout(conte
}
}

fun togglePip() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
context.packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
) {
val activity: Activity? = context.currentActivity
val hasToBuild = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O

if (!pipEnabled) {

val isInPip =
if (hasToBuild) activity!!.isInPictureInPictureMode
else activity!!.isInPictureInPictureMode
if (isInPip) {
activity?.moveTaskToBack(false)
}
return
}

fun togglePip(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& context.packageManager
.hasSystemFeature(
PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
val activity: Activity? = context.currentActivity
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val params = PictureInPictureParams.Builder()
activity?.enterPictureInPictureMode(params.build());
if (hasToBuild) {
val params = PictureInPictureParams.Builder().build()
activity?.enterPictureInPictureMode(params)
} else {
activity?.enterPictureInPictureMode();
activity?.enterPictureInPictureMode()
}

}
}


override fun onHostResume() {
isInBackground = false
}

override fun onHostPause() {}
override fun onHostPause() {
if (pipEnabled) {
isInBackground = true
togglePip()
}
}

override fun onHostDestroy() {
cleanup()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ class AmazonIvsViewManager : SimpleViewManager<AmazonIvsView>() {
view.setAutoQualityMode(autoQualityMode)
}

@ReactProp(name = "pipEnabled")
fun setPipEnabled(view: AmazonIvsView, pipEnabled: Boolean) {
view.setPipEnabled(pipEnabled)
}

@ReactProp(name = "maxBitrate")
fun setMaxBitrate(view: AmazonIvsView, bitrate: Double) {
view.setMaxBitrate(bitrate)
Expand Down
1 change: 1 addition & 0 deletions ios/AmazonIvsManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ @interface RCT_EXTERN_MODULE(AmazonIvsManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(initialBufferDuration, double)
RCT_EXPORT_VIEW_PROPERTY(autoMaxQuality, NSDictionary)
RCT_EXPORT_VIEW_PROPERTY(autoQualityMode, BOOL)
RCT_EXPORT_VIEW_PROPERTY(pipEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(playbackRate, double)
RCT_EXPORT_VIEW_PROPERTY(logLevel, NSNumber)
RCT_EXPORT_VIEW_PROPERTY(progressInterval, NSNumber)
Expand Down
27 changes: 24 additions & 3 deletions ios/AmazonIvsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class AmazonIvsView: UIView, IVSPlayer.Delegate {
self.loop = player.looping
self.liveLowLatency = player.isLiveLowLatency
self.autoQualityMode = player.autoQualityMode
self.pipEnabled = false
self.playbackRate = Double(player.playbackRate)
self.logLevel = NSNumber(value: player.logLevel.rawValue)
self.progressInterval = 1
Expand Down Expand Up @@ -139,6 +140,24 @@ class AmazonIvsView: UIView, IVSPlayer.Delegate {
}
}

@objc var pipEnabled: Bool {
didSet {
guard #available(iOS 15, *), AVPictureInPictureController.isPictureInPictureSupported() else {
return
}
if self.pipController != nil {
self.pipController!.canStartPictureInPictureAutomaticallyFromInline = pipEnabled
self.togglePip()
if !self.pipEnabled {
self.pipController = nil
}
} else {
self.preparePictureInPicture()
}
}
}


@objc var autoMaxQuality: NSDictionary? {
didSet {
let quality = findQuality(quality: autoMaxQuality)
Expand Down Expand Up @@ -259,7 +278,7 @@ class AmazonIvsView: UIView, IVSPlayer.Delegate {
}
if pipController.isPictureInPictureActive {
pipController.stopPictureInPicture()
} else {
} else if self.pipEnabled {
pipController.startPictureInPicture()
}
}
Expand Down Expand Up @@ -453,7 +472,9 @@ class AmazonIvsView: UIView, IVSPlayer.Delegate {
return
}


if !self.pipEnabled {
return
}
if let existingController = self.pipController {
if existingController.ivsPlayerLayer == playerView.playerLayer {
return
Expand All @@ -466,7 +487,7 @@ class AmazonIvsView: UIView, IVSPlayer.Delegate {
}

self.pipController = pipController
pipController.canStartPictureInPictureAutomaticallyFromInline = true
pipController.canStartPictureInPictureAutomaticallyFromInline = self.pipEnabled

}
}
4 changes: 4 additions & 0 deletions src/IVSPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type IVSPlayerProps = {
resizeMode?: ResizeMode;
logLevel?: LogLevel;
progressInterval?: number;
pipEnabled?: boolean;
volume?: number;
quality?: Quality | null;
autoMaxQuality?: Quality | null;
Expand Down Expand Up @@ -95,6 +96,7 @@ export type Props = {
breakpoints?: number[];
maxBitrate?: number;
initialBufferDuration?: number;
pipEnabled?: boolean;
onSeek?(position: number): void;
onData?(data: PlayerData): void;
onVideoStatistics?(data: VideoData): void;
Expand Down Expand Up @@ -132,6 +134,7 @@ const IVSPlayerContainer = React.forwardRef<IVSPlayerRef, Props>(
autoplay = true,
liveLowLatency,
playbackRate,
pipEnabled,
logLevel,
progressInterval,
volume,
Expand Down Expand Up @@ -352,6 +355,7 @@ const IVSPlayerContainer = React.forwardRef<IVSPlayerRef, Props>(
autoQualityMode={autoQualityMode}
breakpoints={breakpoints}
maxBitrate={maxBitrate}
pipEnabled={pipEnabled}
onVideoStatistics={
onVideoStatistics ? onVideoStatisticsHandler : undefined
}
Expand Down

0 comments on commit 9ce7e60

Please sign in to comment.