LORA Short Video
LORA Short Video is an external LORA SDK module that can be used independently.
Features
- Video Grid View
- Video Carousel View
- Video Story Block View
- Video Detail Player (with landscape layout support)
- Playlist
- PiP
Getting started
Project setup
The Short Video module requires a LORA core module, LORA common module, and other third-party libraries to function properly.
In your build.gradle
dependencies:
// sdk aar files & required dependencies
implementation (name:'lora-core-release', ext:'aar')
implementation (name:'lora-common-release', ext:'aar')
implementation (name:'lora-shortvideo-release', ext:'aar')
implementation 'io.insert-koin:koin-android:3.4.0'
implementation 'androidx.media3:media3-exoplayer:1.0.2'
implementation 'androidx.media3:media3-ui:1.0.2'
implementation 'androidx.media3:media3-exoplayer-hls:1.0.2'
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation "com.squareup.okhttp3:logging-interceptor:4.9.0"
implementation 'com.github.bumptech.glide:glide:4.15.1'
kapt 'com.github.bumptech.glide:compiler:4.15.1'
Initialize the SDK
The LORA SDK requires a license key for initialization. Please contact us for information about this key.
Use the following code to initialize the SDK. You can place it in the onCreate
of the main screen or in the application class.
val loraSdkProvider = LoraSdkProvider(context)
loraSdkProvider.init(LICENSE_KEY)
ShortVideoView
ShortVideoView
is a UI entry point designed to display a list of videos in various layout types such as grid, carousel, and story block.
When a video item is clicked, it opens the main player and plays the selected video.
Adding a ShortVideoView
is as simple as adding a normal Android View.
<sg.belive.lib.shortvideo.view.ShortVideoView
android:id="@+id/short_video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
ShortVideoView
loads video data from a Video Source defined by a View Config.
This View Config defines the layout type and provides customization for the UI, as well as controls for basic player behaviors.
Grid layout
The grid layout displays videos vertically.
val cfBuilder = ViewConfig.Builder(this) // `this` is a context
// set the video source (SingleVideoSource, PlaylistVideoSource)
cfBuilder.videoSource(source)
val loCf = ShortVideoGridLayout.createDefaultConfig(this)
cfBuilder.layoutConfig(loCf)
shortVideoView.init(cfBuilder.build())
You can change the Grid span count (default value is 3):
val loCf = ShortVideoGridLayout.createDefaultConfig(this)
loCf.numberOfColumns = 2
Player behavior configuration:
val playerCf = PlayerItemConfiguration().apply {
enableAutoPlay()
actionOnCompleted = PlayerCompleteAction.STOP
}
cfBuilder.playerConfig(playerCf)
And other attributes:
- Item background color
- Spacing between items
Grid Item
For Grid items, you can customize the following UI components/attributes:
- Item width and height ratio (recommended to use a portrait ratio)
- Video title text view
- Play button (set to null to hide)
- Item's corner radius
- Video thumbnail scale mode
val gridLoCf = ShortVideoGridLayout.createDefaultConfig(this)
gridLoCf.ratio = "9:16"
gridLoCf.itemConfiguration?.let { cf ->
cf.title = TitleConfiguration().apply {
this.color = ContextCompat.getColor(context, R.color.bls_sv_video_item_title_color)
this.backgroundRes = R.drawable.bls_sv_bg_carousel_video_item_title
this.textSize =
context.resources.getDimension(R.dimen.bls_sv_video_item_title_size)
this.font = Typeface.DEFAULT
this.gravity = Gravity.START or Gravity.CENTER_VERTICAL
}
cf.playButton = ButtonViewItemConfiguration().apply {
this.onStateIconRes = R.drawable.ic_play
}
cf.cornerRadius = 10F
cf.imageScaleMode = ImageView.ScaleType.CENTER
}
Carousel layout
The Carousel layout displays videos horizontally in a single row.
val cfBuilder = ViewConfig.Builder(this) // `this` is a context
cfBuilder.videoSource(source)
val carouselLoCf = ShortVideoCarouselLayout.createDefaultConfig(this)
cfBuilder.layoutConfig(carouselLoCf)
shortVideoView.init(cfBuilder.build())
Some attributes that can be customized include:
- Item background color
- Spacing between items
Carousel Item
For Carousel items, you can customize the following UI components/attributes:
- Video title text view (the layoutGravity attr is ignored)
- Item's corner radius
- Progress bar
- Play/pause, mute button
- Video thumbnail scale mode
- Video scale mode
val loCf = ShortVideoCarouselLayout.createDefaultConfig(this)
loCf.itemConfiguration?.let { cf ->
cf.videoScaleMode = BlsPlayerScaleMode.DEFAULT
}
Supported video scale modes:
Scale mode | Description |
---|---|
DEFAULT | The SDK will choose the best scale mode bases on video/device orientation. This is the default value and it is recommended to use this mode. |
FIT | Make the video fit the view and keep the ratio in at least 1 dimension (width or height) |
FILL | Zoom the video and do not keep the ratio to fit the view in both width and height |
FIXED_WIDTH | Make the video fit the view width and keep the ratio |
FIXED_HEIGHT | Make the video fit the view height and keep the ratio |
ZOOM | Zoom the video and keep the ratio to fit the view in both width and height |
Story Block layout
Similar to the Carousel layout, the Story Block layout displays videos horizontally, but only one video is visible at a time.
val cfBuilder = ViewConfig.Builder(this) // `this` is a context
cfBuilder.videoSource(source)
val storyBlockLoCf = ShortVideoStoryBlockLayout.createDefaultConfig(this)
cfBuilder.layoutConfig(storyBlockLoCf)
shortVideoView.init(cfBuilder.build())
You have the ability to disable scrolling and customize the next/previous buttons. Below are the attributes available for customization:
- Enable/Disable scrolling
- Container background color
- Item background color
- Previous button (set to null to hide)
- Next button (set to null to hide)
Story Block Item
For Story Block items, you can customize the following UI components/attributes:
- Video title text view (the layoutGravity attr is ignored)
- Item's corner radius
- Progress bar
- Play/pause, mute, full screen, share button
- Video thumbnail scale mode
- Video scale mode
- Product item view
Starting from LORA SDK 1.1.0, this layout type can display overlay data, including product lists, polls, and Q&A. For more information about overlay data, please refer to the Detail Player below.
Detail player
The Short Video module provides a detail player as an internal screen (activity) that opens when clicking on a video item. This screen includes a video player with various functions and an overlay data detail. You can navigate between items by swipe up and down gestures or using navigation buttons. The UI and player behavior can be configured when setting up the Grid, Carousel, or Story Block layout.
val gridCfBuilder = ViewConfig.Builder(this)
// Create the detail view config
val detailCfBuilder = DetailViewConfig.Builder(this)
detailCfBuilder.layoutConfig(ShortVideoDetailLayout.createDefaultConfig(this))
detailCfBuilder.playerConfig(PlayerItemConfiguration())
// Set the detail view config
gridCfBuilder.detailViewConfig(detailCfBuilder.build())
shortVideoView.init(gridCfBuilder.build())
The following attributes can be adjusted:
- Enable/Disable scrolling
- Item background color
- Previous button (set to null to hide)
- Next button (set to null to hide)
Detail Item
For detail items, you can customize the following UI components/attributes:
- Video title, duration text view (the layoutGravity attr is ignored)
- Item's corner radius
- Seek bar
- Play/pause, mute, pip, share, close button
- Video thumbnail scale mode
- Video scale mode
- Product item view.
Product list
A list of products can be attached to a video item, displayed in the main player. Each product item might contain a Shop CTA button that opens the product URL in an external browser (this behavior can be overridden). The product item UI can also be customized.
For product item layout, you can customize the below UI components/attrs:
- Product title text view (the layoutGravity attr is ignored)
- Item's corner radius/background
- Shop CTA text color and icon resource.
- Shop CTA text content. If set, it will override the remote value.
- Product thumbnail scale mode
Q&A item
A Q&A can be attached to a video item and displayed in the detail. Each Q&A item contains a Call to Action (CTA) button that submits an answer. The Q&A item UI can also be customized:
For Q&A item layout, you can customize the below UI components/attrs:
- CTA button: Text Color, Background Color. Other UI components color will be generated from this CTA button colors
Poll item
A Poll can be attached to a video item and displayed in the detail. Each Poll item contains a Call to Action (CTA) button that submits an option. The Poll item UI can also be customized:
For Poll item layout, you can customize the below UI components/attrs:
- CTA button: Text Color, Background Color. Other UI components color will be generated from this CTA button colors
Landscape layout
By default, the detail player renders the UI according to the orientation of the current user's device. The SDK smoothly transitions between orientation modes, switching from portrait to landscape and vice versa without interrupting the player. However, you can also enforce a fixed orientation (portrait or landscape) using the SDK.
val detailLoCf = ShortVideoDetailLayout.createDefaultConfig(this)
detailLoCf.orientationMode = ShortVideoDetailLayout.OrientationMode.LANDSCAPE
Supported orientation modes
- AUTO: Automatically adjust the orientation based on the device's orientation.
- LANDSCAPE: Enforce a landscape orientation.
- PORTRAIT: Enforce a portrait orientation.
Picture in Picture (PiP)
The detail player supports playing a video in Picture in Picture (PiP) mode on devices that support PiP (Android 8+). You can disable this feature by hiding the PiP button. When a video is playing in this mode, it will always loop regardless of the player completion action.
Player behaviors
Auto play
This auto play flag causes a video to play when it becomes visible on the screen. If there are multiple visible videos, the first video will be played. The default value is true.
val playerCf = PlayerItemConfiguration().apply {
enableAutoPlay()
//
disableAutoPlay()
}
Player complete action
You can control the behavior when the player finishes playback.
val playerCf = PlayerItemConfiguration().apply {
actionOnCompleted = PlayerCompleteAction.STOP
}
Supported Actions:
Action | Description |
---|---|
STOP | The player will always stop the video after playing it. |
REPEAT | The player will always loop the current video. |
PLAY_NEXT_ITEM | The player will always play the next video in the list after playing the current video. If the current video is the last item, the player will stop playing. This is the default value. |
PLAY_NEXT_ITEM_AND_LOOP | The player will always play the next video in the list after playing the current video. If the current video is the last item, the player will play the first item in the list. This behavior is same as the Loop from start setting at the CMS. |
Video source
Playlist
The playlist video source fetches all available videos from a specific playlist by its ID. To create a playlist source, use the following API:
ShortVideoSource.playlist(playlistAlias, maxVideoItemsCount)
Setting a maxVideoItemsCount
greater than 0 will limit the number of videos to load.
Single
The single video source fetches a single video by its video ID. To create a single source, use the following API:
ShortVideoSource.singleVideo(videoId)
Play and pause
You can pause and resume the video by calling the following APIs:
shortVideoView.pause()
//
shortVideoView.play()
Listeners
Error listener
When an error occurs, the Short Video module triggers an error callback with a code and a message.
To listen to errors, set a BlsShortVideoErrorListener
to the ShortVideoView
.
shortVideoView.setErrorListener(object : BlsShortVideoErrorListener {
override fun onShortVideoError(code: Int, msg: String?) {
}
})
The error code can be found in the BlsShortVideoErrorCode
.
Video item click listener
When a user clicks on a video item, it opens the main player and triggers a callback.
shortVideoView.setVideoItemClickedListener(object : BlsShortVideoItemClickListener {
override fun onShortVideoItemClicked(videoId: String) {
}
})
The implementation of the listener mainly serves analytics purposes and does not affect the flow.
Detail player action listener
This listener is different from other listeners as it's bound to a singleton handler. To avoid memory leaks, avoid implementing this interface as an anonymous class in the activity context. Instead, create a class and implement the interface.
class MainPlayerAction : BlsShortVideoMainPlayerActionListener {
override fun onProductItemClicked(
context: Context, item: ShortVideoProductModel
): Boolean {
context.openBrowser(item.productUrl.orEmpty())
return true
}
override fun onShareVideo(context: Context, videoId: String): Boolean {
context.shareText(videoId)
return true
}
override fun onSubmitPollError(context: Context, errorCode: Int) {
}
override fun onSubmitDefaultAnswerError(context: Context, errorCode: Int) {
}
override fun onSubmitFollowupAnswerError(context: Context, errorCode: Int) {
}
}
The onProductItemClicked
method is triggered when a shop CTA button is clicked. Returning true
in this method consumes the event and stops the flow.
If false
is returned, the SDK continues to handle the event.
The onShareVideo
method is triggered when a share button is clicked (in both Carousel and Main player). Returning true
consumes the event and stops the flow.
If false
is returned, the SDK continues to handle the event, and the default behavior is to open the system share dialog.
The onSubmitPollError
method is triggered when submitting a poll option fails.
The onSubmitDefaultAnswerError
method is triggered when submitting a default answer fails.
The onSubmitFollowupAnswerError
method is triggered when submitting a follow-up answer fails.