1.0.0 • Published 3 years ago

react-native-jwplayer-extended v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

react-native-jw-media-player

A react-native bridge for JWPlayer native SDK's

Getting started

npm i react-native-jw-media-player --save

Mostly automatic installation

For iOS you have to run cd ios/ && pod install.

For Android the package is automatically linked.

Important

This README is for react-native-jw-media-player version 0.2.0 and higher, for previous version check out the Old README.

Since version 0.2.0 we use the new JWPlayerKit && SDK 4 check out iOS get started && Android get started

Android dependencies

Insert the following lines inside the allProjects.dependencies block in android/build.gradle:

maven{
    url 'https://mvn.jwplayer.com/content/repositories/releases/'
}

As so

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url("$rootDir/../node_modules/react-native/android")
        }
        maven {
            // Android JSC is installed from npm
            url("$rootDir/../node_modules/jsc-android/dist")
        }

        google()
        jcenter()
        maven { url 'https://jitpack.io' }
        // Add these lines
        maven{
            url 'https://mvn.jwplayer.com/content/repositories/releases/'
        }
    }
}

Usage

...

import JWPlayer, { JWPlayerState } from 'react-native-jw-media-player';

...

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  player: {
    flex: 1,
  },
});

...

const playlistItem = {
  title: 'Track',
  mediaId: -1,
  image: 'http://image.com/image.png',
  description: 'My beautiful track',
  startTime: 0,
  file: 'http://file.com/file.mp3',
  autostart: true,
  repeat: false,
  displayDescription: true,
  displayTitle: true,
  tracks: [
    {
      file: 'http://file.com/english.vtt',
      label: 'en'
    },
    {
      file: 'http://file.com/spanish.srt',
      label: 'es'
    }
  ],
  sources: [
    {
      file: 'http://file.com/file.mp3',
      label: 'audio'
    },
    {
      file: 'http://file.com/file.mp4',
      label: 'video',
      default: true
    }
  ]
}

const config = {
  license:
    Platform.OS === 'android'
      ? 'YOUR_ANDROID_SDK_KEY'
      : 'YOUR_IOS_SDK_KEY',
  backgroundAudioEnabled: true,
  autostart: true,
  styling: {
    colors: {
      timeslider: {
        rail: "0000FF",
      },
    },
  },
  playlist: {
    [playlistItem],
  },
}

...

async isPlaying() {
  const playerState = await this.JWPlayer.playerState();
  return playerState === JWPlayerState.JWPlayerStatePlaying;
}

...

render() {

...

<View style={styles.container}>
  <JWPlayer
    ref={p => (this.JWPlayer = p)}
    style={styles.player}
    config={config}
    onBeforePlay={() => this.onBeforePlay()}
    onPlay={() => this.onPlay()}
    onPause={() => this.onPause()}
    onIdle={() => console.log("onIdle")}
    onPlaylistItem={event => this.onPlaylistItem(event)}
    onSetupPlayerError={event => this.onPlayerError(event)}
    onPlayerError={event => this.onPlayerError(event)}
    onBuffer={() => this.onBuffer()}
    onTime={event => this.onTime(event)}
    onFullScreen={() => this.onFullScreen()}
    onFullScreenExit={() => this.onFullScreenExit()}
  />
</View>

...

}

Run example project

Running the example project:

  1. Checkout this repository.
  2. Go to Example directory and run yarn or npm i
  3. Go to Example/ios and install Pods with pod install
  4. Open RNJWPlayer.xcworkspace with XCode.
  5. Add your JW SDK license in App.js under the configprop.

Available props

PropDescriptionType
configThe JW Config object.Object
Config
PropDescriptionTypePlatformDefault
offlineImageThe url for the player offline thumbnail.StringiOSnone
offlineMessageThe message when the player is offline.StringiOSnone
autostartShould the tracks auto start.BooleaniOS && Androidfalse
controlsShould the control buttons show.BooleanAndroidtrue
repeatShould the track repeat.BooleaniOS && Androidfalse
playlistAn array of playlistItems.[playlistItem] see PlaylistItem]iOS && Androidnone
nextUpStyleHow the next up videos should be presented.{offsetSeconds: Int, offsetPercentage, Int}iOS && Androidnone
stylingAll the stylings for the player see Styling section.ObjectiOS && Androidnone
advertisingGeneral Advertising settings on the player see Advertising section.ObjectiOS && Androidnone
fullScreenOnLandscapeWhen this is true the player will go into full screen on rotate of phone to landscapeBooleaniOS && Androidfalse
landscapeOnFullScreenWhen this is true the player will go into landscape orientation when on full screenBooleaniOS && Androidfalse
portraitOnExitFullScreenWhen this is true the player will go into portrait orientation when exiting full screenBooleanAndroidfalse
exitFullScreenOnPortraitWhen this is true the player will exit full screen when the phone goes into portraitBooleanAndroidfalse
enableLockScreenControlsWhen this is true the player will show media controls on lock screenBooleaniOStrue
stretchingResize images and video to fit player dimensions. See below Stretching section.StringAndroidnone
backgroundAudioEnabledShould the player continue playing in the background and handle interruptions.BooleaniOS && Androidfalse
viewOnlyWhen true the player will not have any controls it will show only the video.BooleaniOSfalse
pipEnabledWhen true the player will be able to go into Picture in Picture mode. Note: This is true by default for iOS PlayerViewController. For Android you will also need to follow the instruction mentioned here && below Picture in picture section.BooleaniOS when viewOnly prop is true && Androidfalse
interfaceBehaviorThe behavior of the player interface.'normal', 'hidden', 'onscreen'iOSnormal
preloadThe behavior of the preload.'auto', 'none'iOSauto
relatedThe related videos behaviors. Check out the Related section.ObjectiOSnone
hideUIGroupA way to hide a certain UI group in the player.'overlay', 'control_bar', 'center_controls', 'next_up', 'error', 'playlist', 'controls_container', 'settings_menu', 'quality_submenu', 'captions_submenu', 'playback_submenu', 'audiotracks_submenu', 'casting_menu'Androidnone
PlaylistItem
PropDescriptionType
mediaIdThe JW media id.Int
startTimethe player should start from a certain second.Int
adVmapThe url of ads VMAP xml.String
adScheduleArray of tags and and offsets for ads.{tag: String, offset: String}
descriptionDescription of the track.String
fileThe url of the file to play.String
tracksArray of caption tracks.{file: String, label: String}
sourcesArray of media sources.{file: String, label: String, default: Boolean}
imageThe url of the player thumbnail.String
titleThe title of the track.String
recommendationsUrl for recommended videos.String
autostartShould the track auto start.Boolean
JWPlayerAdClients
ClientValue
JWAdClientVast0
JWAdClientGoogima1
JWAdClientGoogimaDAI2
JWPlayerState

iOS

StateValue
JWPlayerStateUnknown0
JWPlayerStateIdle1
JWPlayerStateBuffering2
JWPlayerStatePlaying3
JWPlayerStatePaused4
JWPlayerStateComplete5
JWPlayerStateError6

Android

StateValue
JWPlayerStateIdle0
JWPlayerStateBuffering1
JWPlayerStatePlaying2
JWPlayerStatePaused3
JWPlayerStateComplete4
JWPlayerStateError5
Styling
PropDescriptionTypePlatformDefault
displayDescriptionShould the player show the description.BooleaniOS && Androidtrue
displayTitleShould the player show the title.BooleaniOS && Androidtrue
colorsObject with colors in hex format (without hashtag), for the icons and progress bar See below Colors section.Object
fontName and size of the fonts for all texts in the player. Note: the font must be added properly in your native project{name: String, size: Int}iOSSystem
captionsStyleStyle of the captions: name and size of the fonts, backgroundColor, edgeStyle and highlightColor. Note: the font must be added properly in your native project{font: {name: String, size: Int}, backgroundColor: String, highlightColor: String, edgeStyle: 'none', 'dropshadow', 'raised', 'depressed', 'uniform'} See the edgeStyle enum belowiOSSystem
menuStyleStyle of the menu: name and size of the fonts, backgroundColor and fontColor. Note: the font must be added properly in your native project{font: {name: String, size: Int}, backgroundColor: String, fontColor: String}iOSSystem
Colors
PropDescriptionTypePlatformDefault
buttonsColor of all the icons.StringiOSFFFFFF
timesliderColors for the progress bar.{progress: String, buffer: String, rail: String, thumb: String,}iOS & Android **Note: buffer is only available on android**FFFFFF
backgroundColorColor for the background.StringiOS & AndroidFFFFFF

Note: It is expected to pass the colors in hex format without the hashtag example for white FFFFFF.

colors: PropTypes.shape({
  buttons: PropTypes.string,
  timeslider: PropTypes.shape({
    progress: PropTypes.string,
    rail: PropTypes.string,
    thumb: PropTypes.string,
  })
})
EdgeStyle
StateValue
JWCaptionEdgeStyleUndefined1
JWCaptionEdgeStyleNone2
JWCaptionEdgeStyleDropshadow3
JWCaptionEdgeStyleRaised4
JWCaptionEdgeStyleDepressed5
JWCaptionEdgeStyleUniform6

AudioTrack

Each AudioTrack object has the following keys:

autoSelect: boolean

defaultTrack: boolean

groupId: string

name: string

language: string

A video file can include multiple audio tracks. The onAudioTracks event is fired when the list of available AudioTracks is updated (happens shortly after a playlist item starts playing).

Once the AudioTracks list is available, use getAudioTracks to return an array of available AudioTracks.

Then use getCurrentAudioTrack or setCurrentAudioTrack(index) to view or change the current AudioTrack.

This is all handled automatically if using the default player controls, but these functions are helpful if you're implementing custom controls.

Stretching

uniform: (default) Fits JW Player dimensions while maintaining aspect ratio

exactFit: Will fit JW Player dimensions without maintaining aspect ratio

fill: Will zoom and crop video to fill dimensions, maintaining aspect ratio

none: Displays the actual size of the video file. (Black borders)

Stretching Examples:

Stretching Example

(image from JW Player docs - here use exactFit instead of exactfit)

Advertising
PropDescriptionType
adVmapThe url of ads VMAP xml.String
adScheduleArray of tags and and offsets for ads.{tag: String, offset: String}
openBrowserOnAdClickShould the player open the browser when clicking on an ad.Boolean
adClientThe ad client. One of JWPlayerAdClients, defaults to JWAdClientVast'vast', 'ima", 'ima_dai'
Related
PropDescriptionType
onClickSets the related content onClick action using a JWRelatedOnClick. Defaults to play'play', 'link'
onCompleteSets the related content onComplete action using a JWRelatedOnComplete. Defaults to show'show', 'hide', 'autoplay'
headingSets the related content heading using a String. Defaults to “Next up”.String
urlSets the related content url using a URL.String
autoplayMessageSets the related content autoplayMessage using a String. Defaults to titleString
autoplayTimerSets the related content autoplayTimer using a Int. Defaults to 10 seconds.Int
Picture-in-picture

Picture in picture mode is enabled by JW on iOS for the PlayerViewController, however when setting the viewOnly prop to true you will also need to set the pipEnabled prop to true, and call the togglePIP method to enable / disable PIP. For Android you will have to add the following code in your MainActivity.java

@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
  super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);

  Intent intent = new Intent("onPictureInPictureModeChanged");
  intent.putExtra("isInPictureInPictureMode", isInPictureInPictureMode);
  intent.putExtra("newConfig", newConfig);
  this.sendBroadcast(intent);
}

Available methods

FuncDescriptionArgument
seekToTells the player to seek to position, use in onPlaylistItem callback so player finishes buffering file.Int
togglePIPEnter or exist Picture in picture mode.none
playStarts playing.none
pausePauses playing.none
stopStops the player completely.none
playerStateReturns promise that then returns the current state of the player. Check out the JWPlayerState Object.none
positionReturns promise that then returns the current position of the player in seconds.none
toggleSpeedToggles the player speed one of 0.5, 1.0, 1.5, 2.0.none
setSpeedSets the player speed.Double
setPlaylistIndexSets the current playing item in the loaded playlist.Int
setControlsSets the display of the control buttons on the player.Boolean
setFullScreenSet full screen.Boolean
loadPlaylistLoads a playlist. (Using this function before the player has finished initializing may result in assert crash or blank screen, put in a timeout to make sure JWPlayer is mounted).[PlaylistItems]
loadPlaylistItemLoads a playlist item. (Using this function before the player has finished initializing may result in assert crash or blank screen, put in a timeout to make sure JWPlayer is mounted).PlaylistItem
getAudioTracksReturns promise that returns an array of AudioTracksnone
getCurrentAudioTrackReturns promise that returns the index of the current audio track in array returned by getAudioTracksnone
setCurrentAudioTrackSets the current audio track to the audio track at the specified index in the array returned by getAudioTracksInt

Available callbacks

FuncDescriptionArgument
onPlaylistA new playlist is loaded.[playlistItem] see PlaylistItem
onPlayerReadyThe player has finished setting up and is ready to play.none
onBeforePlayRight before playing.none
onBeforeCompleteRight before playing completed and is starting to play.none
onCompleteRight after media playing is completed.none
onPlayPlayer started playing.none
onPausePlayer paused playing.none
onSeekSeek event requested from user.{position: Double, offset: Double}
onSeekedPlayer finished seeking to a new position.On iOS none, On Android {position: Double}
onSetupPlayerErrorPlayer faced and error while setting up the player.{error: String}
onPlayerErrorPlayer faced an error after setting up the player but when attempting to start playing.{error: String}
onBufferThe player is buffering.none
onTimeInterval callback for every millisecond playing.{time: Double, duration: Double}
onFullScreenRequestedUser clicked on the fullscreen icon. Use this to resize the container view for the player, if your not using nativeFullScreen prop. (Make use of https://github.com/yamill/react-native-orientation for fullscreen mode)none
onFullScreenPlayer went into fullscreen. Use this to resize the container view for the player, if your not using nativeFullScreen prop. (Make use of https://github.com/yamill/react-native-orientation for fullscreen mode)none
onFullScreenExitRequestedUser clicked on the fullscreen icon to exit.none
onFullScreenExitPlayer exited fullscreen.none
onPlaylistCompletePlayer finished playing playlist items.none
onPlaylistItemWhen starting to play a playlist item.JW type playlist item see docs ios, android contains additional index of current playing item in playlist 0 for default
onAudioTracksThe list of available audio tracks is updated (happens shortly after a playlist item starts playing).none

Background Audio

This package supports Background audio sessions by setting the backgroundAudioEnabled prop on the PlaylistItem, just follow the JWPlayer docs for background session.

Here for Android https://developer.jwplayer.com/jwplayer/docs/android-audiotrack#background-audio although this package handles background audio playing in android as is and you shouldn't have to make any additional changes.

Here for iOS https://developer.jwplayer.com/jwplayer/docs/ios-behavior#background-audio under Background Audio section.

For iOS you will have to enable audio in Signing & Capabilities under background modes.

Casting

JWPlayer enables casting by default with a casting button (if you pass the viewOnly prop in the player config on iOS then you will need to enable casting by yourself).

iOS

Follow the instruction here on the official JWPlayer site.

Edit your Info.plist with the following values:

'NSBluetoothAlwaysUsageDescription' => 'We will use your Bluetooth for media casting.',
'NSBluetoothPeripheralUsageDescription' => 'We will use your Bluetooth for media casting.',
'NSLocalNetworkUsageDescription' => 'We will use the local network to discover Cast-enabled devices on your WiFi network.',
'Privacy - Local Network Usage Description' => 'We will use the local network to discover Cast-enabled devices on your WiFi network.'
'NSMicrophoneUsageDescription' => 'We will use your Microphone for media casting.'

Enable Access WiFi Information capability under Signing & Capabilities

Available methods

For iOS
FuncDescriptionArgument
castStateGets the cast state.int check out GCKCastState
GCKCastState
typedef NS_ENUM(NSUInteger, GCKCastState) {
  /** No Cast session is established, and no Cast devices are available. */
  GCKCastStateNoDevicesAvailable = 0,
  /** No Cast session is establishd, and Cast devices are available. */
  GCKCastStateNotConnected = 1,
  /** A Cast session is being established. */
  GCKCastStateConnecting = 2,
  /** A Cast session is established. */
  GCKCastStateConnected = 3,
};

Available callbacks

For iOS
FuncDescriptionPayload
onCastingDevicesAvailableCasting were devices discovered and became available.{devices: [{name: string, identifier: string}}]
onConnectedToCastingDeviceConnected to cast device.{device: {name: string, identifier: string}}
onDisconnectedFromCastingDeviceDisconnected from cast device.{error: Error}
onConnectionTemporarilySuspendedDisconnected temporarily from cast device.none
onConnectionRecoveredConnection to cast device recoverednone
onCastingStarted castingnone
onConnectionFailedConnection to cast device failed.{error: Error}
onCastingEndedCasting ended.{error: Error}
onCastingFailedCasting failed.{error: Error}
For Android
FuncDescriptionPayload
onCastCasting event occurred{active: Boolean, available: Boolean, device: String}

CHANGELOG