StoryBlock (Android)
StoryBlock
component allows the host app to embed the Fireworks video player directly into its view hierarchy.

StoryBlock is a heavy object containing multiple instances of the player, Heavy-lifting UI elements, and intensive background tasks, Beware that the recommended number of the StoryBlock being used in a single screen is 1. However, in a wide range of new Android devices, 2 instances might work alright. Any number of StoryBlock above this limitation is not recommended by the Firework team and is not supported.
StoryBlock lifecycle is very simple, the host app needs to create an instance of StoryBlock and initialise it once, then the StoryBlock goes to live mode and works as expected until the host app decides to kill the lifecycle, so call the destroy function. The init
function must not be called more than once, as same as destroy
function. The SDK trusts the host app to use these handles as expected, any violation of the lifecycle use might lead to unexpected behaviour of StoryBlock.
Lifecycle

Integration
To include a StoryBlock
in your app, add it to your app's layout, and initialise it by calling init()
method.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="300dp"
android:layout_height="400dp"
android:layout_gravity="center"
android:layout_marginVertical="16dp">
<com.firework.storyblock.FwStoryBlockView
android:id="@+id/story_block"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="9:16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Initialisation of the StoryBlock
the component is as below
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewOptions = viewOptions {
baseOptions {
feedResource(FeedResource.Discovery)
}
playerOptions {
playerMode(PlayerMode.FIT_MODE)
}
storyBlockOptions {
enableAutoPlay(true)
showFullScreenIcon(true)
}
}
binding.storyBlock.init(
fragmentManager = supportFragmentManager,
lifecycle = lifecycle,
viewOptions = viewOptions,
pauseWhenNotVisible = true,
)
}
}
When you set the pauseWhenNotVisible
parameter to true
in the init()
function, the StoryBlock
will take automatic action to pause (or mute, in the case of a livestream) its playback whenever it becomes invisible on the screen. It will then resume normal playback when it becomes visible again.
Calling storyblock.destroy()
releases all resources allocated for the StoryBlock
.
StoryBlock
standalone configurations
StoryBlock
standalone configurationsYou can choose whether to enable autoplay mode or not; it's turned on by default.
You can also decide if you want to display the full-screen icon on the story block by adjusting the settings in storyBlockOptions
; the default setting for this is true.
val viewOptions = viewOptions {
baseOptions {
feedResource(FeedResource.Discovery)
}
playerOptions {
playerMode(PlayerMode.FIT_MODE)
}
storyBlockOptions {
enableAutoPlay(true)
showFullScreenIcon(true)
}
}
binding.storyBlock.init(
fragmentManager = supportFragmentManager,
lifecycle = lifecycle,
viewOptions = viewOptions,
pauseWhenNotVisible = true,
)
StoryBlock
player modes
StoryBlock
player modesYou may choose between two-player modes for the StoryBlock
:
FIT_MODE
FULL_BLEED_MODE
When StoryBlock
is set up to display video in PlayerMode.FIT_MODE
, internally it tries to scale video with 9:16
dimension ratio. To achieve the proper result StoryBlock
the container should be placed into ConstraintLayout
with app:layout_constraintDimensionRatio="9:16"
attribute:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_gravity="center"
android:layout_marginVertical="16dp">
<com.firework.storyblock.FwStoryBlockView
android:id="@+id/story_block"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="9:16" \\ this property is needed for FIT_MODE
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
If StoryBlock
is set up with FULL_BLEED_MODE
, it will just fill in the container following its width and height.
Fullscreen and Compact state
StoryBlock
maybe displayed in fullscreen and compact mode
When the StoryBlock
is in the compact mode it displays a limited set of components. For example, shopping and livestream chat components are supported only in fullscreen mode.
It is possible to open the fullscreen mode programmatically by calling:
storyBlock.openFullscreen()
Play and pause the video in StoryBlock
StoryBlock
Users can pause and resume the video by calling the following functions
storyBlock.pause()
// and
storyBlock.play()
Keep in mind that pause()
function will not work for livestreams.
Monitoring feed loading states and handling errors that occur during StoryBlock operation
The FwStoryBlockView
class provides two key listener methods for monitoring feed loading states and handling errors that occur during StoryBlock operation.
setFeedLoadListener
fun setFeedLoadListener(feedLoadListener: FeedLoadListener?)
Description: Sets a listener to monitor the feed loading state of the StoryBlock. This listener provides real-time updates about the loading process, including when the feed is being loaded, when it has successfully loaded, or when it's empty.
Parameters:
feedLoadListener
: An optionalFeedLoadListener
instance. Passnull
to remove an existing listener.
Listener Interface:
fun interface FeedLoadListener {
fun onFeedLoadStateChanged(feedLoadState: FeedLoadState)
}
Feed Load States:
FeedLoadState.Loading
: The feed is currently being loaded from the serverFeedLoadState.FeedLoaded
: The feed has been successfully loaded and is ready for displayFeedLoadState.EmptyFeed
: The feed was loaded successfully but contains no contentFeedLoadState.EndOfFeed
: The end of the feed has been reached
Usage Example:
storyBlockView.setFeedLoadListener { state ->
when (state) {
is FeedLoadState.Loading -> {
// Show loading indicator
showLoadingProgress()
}
is FeedLoadState.FeedLoaded -> {
// Hide loading indicator and enable interactions
hideLoadingProgress()
enableUserInteractions()
}
is FeedLoadState.EmptyFeed -> {
// Show empty feed message
showEmptyFeedMessage()
}
is FeedLoadState.EndOfFeed -> {
// Handle end of feed scenario
showEndOfFeedMessage()
}
}
}
Best Practices:
Set the listener before calling
init()
to ensure you receive all state changesHandle all possible
FeedLoadState
values in your implementationRemove the listener by passing
null
when the StoryBlock is no longer neededUse this listener to coordinate UI updates with the loading state
setOnErrorListener
fun setOnErrorListener(listener: FwErrorListener)
Description: Sets a listener to handle errors that occur during StoryBlock operation. This listener receives notifications about various types of errors, including SDK initialization errors, network issues, and StoryBlock-specific errors.
Parameters:
listener
: AFwErrorListener
instance that will receive error notifications
Listener Interface:
fun interface FwErrorListener {
fun onFwError(error: FwError)
}
Error Types: The listener can receive various error types including:
SdkLevelError.SdkNotInitialized
: The Firework SDK has not been initializedStoryBlockError.InitializationFailed
: StoryBlock initialization failedStoryBlockError.DestructionFailed
: StoryBlock destruction failedNetworkError
: Network-related errors during feed loadingPlayerError
: Video playback errorsLivestreamError
: Live streaming specific errors
Usage Example:
storyBlockView.setOnErrorListener { error ->
when (error) {
is SdkLevelError.SdkNotInitialized -> {
// Handle SDK not initialized error
showSdkInitializationError()
initializeSdk()
}
is StoryBlockError.InitializationFailed -> {
// Handle StoryBlock initialization failure
showInitializationError(error.message)
}
is NetworkError -> {
// Handle network-related errors
showNetworkError()
retryNetworkRequest()
}
is PlayerError -> {
// Handle video playback errors
showPlaybackError()
}
else -> {
// Handle other error types
showGenericError(error::class.java.simpleName)
}
}
// Log the error for debugging
Log.e("StoryBlock", "Error occurred: ${error::class.java.simpleName}")
}
Error Management:
The method automatically manages error listener registration and cleanup
When setting a new listener, any existing listener is automatically removed
The listener is automatically removed when the StoryBlock is destroyed
Removing Error Listener:
// To remove the error listener
storyBlockView.removeOnErrorListener(listener)
Integration Example
Here's a complete example showing both listeners working together:
class StoryBlockActivity : AppCompatActivity() {
private lateinit var storyBlockView: FwStoryBlockView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_story_block)
storyBlockView = findViewById(R.id.storyBlockView)
// Set up listeners before initialization
setupListeners()
// Initialize the StoryBlock
initializeStoryBlock()
}
private fun setupListeners() {
// Feed loading listener
storyBlockView.setFeedLoadListener { state ->
handleFeedLoadState(state)
}
// Error listener
storyBlockView.setOnErrorListener { error ->
handleError(error)
}
}
private fun initializeStoryBlock() {
val viewOptions = ViewOptions.Builder()
.setFeedId("your-feed-id")
.build()
storyBlockView.init(
fragmentManager = supportFragmentManager,
lifecycleOwner = this,
viewOptions = viewOptions
)
}
private fun handleFeedLoadState(state: FeedLoadState) {
when (state) {
is FeedLoadState.Loading -> {
binding.progressBar.visibility = View.VISIBLE
binding.errorView.visibility = View.GONE
binding.emptyView.visibility = View.GONE
}
is FeedLoadState.FeedLoaded -> {
binding.progressBar.visibility = View.GONE
// StoryBlock is ready for interaction
}
is FeedLoadState.EmptyFeed -> {
binding.progressBar.visibility = View.GONE
binding.emptyView.visibility = View.VISIBLE
}
is FeedLoadState.EndOfFeed -> {
// Handle end of feed
}
}
}
private fun handleError(error: FwError) {
binding.progressBar.visibility = View.GONE
when (error) {
is SdkLevelError.SdkNotInitialized -> {
showError("SDK not initialized. Please initialize the SDK first.")
}
is NetworkError -> {
showError("Network error. Please check your connection.")
}
else -> {
showError("An error occurred: ${error::class.java.simpleName}")
}
}
}
override fun onDestroy() {
super.onDestroy()
// Clean up listeners
storyBlockView.setFeedLoadListener(null)
storyBlockView.removeOnErrorListener(errorListener)
storyBlockView.destroy()
}
}
Automatically release StoryBlock (Deprecated, please use FwStoryBlockView instead)
The FwLifecycleAwareStoryBlockView
is a wrapper for the FwStoryBlockView
class, providing automatic cleanup when the parent component (Fragment or Activity) is destroyed.
To utilize and set up the FwLifecycleAwareStoryBlockView
, follow the same procedures as you would for the FwStoryBlockView
. The only difference is that the destroy()
method will be triggered automatically when needed.
Last updated
Was this helpful?