Audience Polls during Live Stream - Android
Interactive polls are a great way to increase engagement during livestreams. Using VideoSDK’s PubSub mechanism, you can easily implement real-time audience polling, where viewers can vote and see live results instantly.
This guide walks you through how to create, send, and visualize poll results during a livestream.
Step 1: Creating and Publishing a Poll
To initiate a poll, use the PubSub class with a POLL topic. The poll structure should include a question and multiple options. This message will be published to all participants.
- Kotlin
- Java
class CreatePollDialog() {
    
    companion object {
        const val POLL_TOPIC = "POLL"
    }
    
    fun show() {
        // ... UI setup code ...
        
        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
            // Validate inputs
            
            // Create poll object
            val options = mutableListOf(option1, option2)
            if (option3.isNotEmpty()) options.add(option3)
            if (option4.isNotEmpty()) options.add(option4)
            
            val poll = SimplePoll(question, options)
            
            // Publish poll to all participants
            val pubSubPublishOptions = PubSubPublishOptions()
            pubSubPublishOptions.isPersist = true
            liveStream.pubSub.publish(POLL_TOPIC, poll.toJsonString(), pubSubPublishOptions)
            
            // Show results dialog to host
            PollResultsDialog(context, liveStream).show(poll)
            
            dialog.dismiss()
        }
    }
}
public class CreatePollDialog {
public static final String POLL_TOPIC = "POLL";
public CreatePollDialog() {
    // default constructor
}
public void show() {
    // ... UI setup code ...
    dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> {
        // Validate inputs
        // Create poll object
        List<String> options = new ArrayList<>();
        options.add(option1);
        options.add(option2);
        if (!option3.isEmpty()) options.add(option3);
        if (!option4.isEmpty()) options.add(option4);
        SimplePoll poll = new SimplePoll(question, options);
        // Publish poll to all participants
        PubSubPublishOptions pubSubPublishOptions = new PubSubPublishOptions();
        pubSubPublishOptions.setPersist(true);
        liveStream.pubSub.publish(POLL_TOPIC, poll.toJsonString(), pubSubPublishOptions);
        // Show results dialog to host
        new PollResultsDialog(context, liveStream).show(poll);
        dialog.dismiss();
    });
  }
}
Step 2: Subscribing to Polls and Displaying Options
Participants can listen to the POLL topic and render voting options dynamically based on the incoming data.
- Kotlin
- Java
class PollVotingDialog() {
    
    companion object {
        const val POLL_RESPONSE_TOPIC = "POLL_RESPONSE"
    }
    
    fun show(poll: SimplePoll) {
        // ... UI setup code ...
        
        // Create option buttons dynamically
        poll.options.forEach { option ->
            val button = Button(context)
            button.text = option
            button.setOnClickListener {
                // Submit vote
                val response = SimplePollResponse(
                    pollId = poll.id,
                    option = option,
                    participantId = liveStream.localParticipant.id,
                    participantName = liveStream.localParticipant.displayName
                )
                
                liveStream.pubSub.publish(POLL_RESPONSE_TOPIC, response.toJsonString())
                
                // Disable all buttons after voting
                for (i in 0 until optionsContainer.childCount) {
                    optionsContainer.getChildAt(i).isEnabled = false
                }
            }
            
            optionsContainer.addView(button)
        }
    }
}
public class PollVotingDialog {
    public static final String POLL_RESPONSE_TOPIC = "POLL_RESPONSE";
    public void show(SimplePoll poll) {
        // ... UI setup code ...
        // Create option buttons dynamically
        for (String option : poll.getOptions()) {
            Button button = new Button(context);
            button.setText(option);
            button.setOnClickListener(v -> {
                // Submit vote
                SimplePollResponse response = new SimplePollResponse(
                        poll.getId(),
                        option,
                        liveStream.getLocalParticipant().getId(),
                        liveStream.getLocalParticipant().getDisplayName()
                );
                liveStream.pubSub.publish(POLL_RESPONSE_TOPIC, response.toJsonString());
                // Disable all buttons after voting
                for (int i = 0; i < optionsContainer.getChildCount(); i++) {
                    optionsContainer.getChildAt(i).setEnabled(false);
                }
            });
            optionsContainer.addView(button);
        }
    }
}
Step 3: Aggregating and Displaying Poll Results
The host can subscribe to the POLL_RESPONSE topic to collect responses and render the result in real-time.
- Kotlin
- Java
class PollResultsDialog() {
    
    private val pollResults = ConcurrentHashMap<String, Int>()
    private var totalVotes = 0
    
    companion object {
        const val POLL_RESPONSE_TOPIC = "POLL_RESPONSE"
    }
    
    fun show(poll: SimplePoll) {
        // ... UI setup code ...
        
        // Initialize results map with 0 votes for each option
        poll.options.forEach { option ->
            pollResults[option] = 0
        }
        
        // Create initial result bars
        updateResultBars()
        
        // Listen for poll responses
        responsesListener = PubSubMessageListener { pubSubMessage ->
            try {
                val response = SimplePollResponse.fromJsonString(pubSubMessage.message)
                val option = response.option
                
                // Update vote count
                pollResults[option] = (pollResults[option] ?: 0) + 1
                totalVotes++
                
                // Update UI on main thread
                (context as? android.app.Activity)?.runOnUiThread {
                    updateResultBars()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        
        // Subscribe to poll responses
        liveStream.pubSub.subscribe(POLL_RESPONSE_TOPIC, responsesListener)
    }
    
    private fun updateResultBars() {
        // Clear previous results
        optionsContainer?.removeAllViews()
        
        // Create result bars for each option
        pollResults.forEach { (option, votes) ->
            val percentage = if (totalVotes > 0) (votes * 100) / totalVotes else 0
            
            // Create progress bar UI showing percentage
            // ... UI code to display results ...
        }
    }
}
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
public class PollResultsDialog {
    private ConcurrentHashMap<String, Integer> pollResults = new ConcurrentHashMap<>();
    private int totalVotes = 0;
    public static final String POLL_RESPONSE_TOPIC = "POLL_RESPONSE";
    public void show(SimplePoll poll) {
        // ... UI setup code ...
        // Initialize results map with 0 votes for each option
        for (String option : poll.options) {
            pollResults.put(option, 0);
        }
        // Create initial result bars
        updateResultBars();
        // Listen for poll responses
        responsesListener = new PubSubMessageListener() {
            @Override
            public void onMessage(PubSubMessage pubSubMessage) {
                try {
                    SimplePollResponse response = SimplePollResponse.fromJsonString(pubSubMessage.message);
                    String option = response.option;
                    // Update vote count
                    pollResults.put(option, pollResults.getOrDefault(option, 0) + 1);
                    totalVotes++;
                    // Update UI on main thread
                    if (context instanceof android.app.Activity) {
                        ((android.app.Activity) context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                updateResultBars();
                            }
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        // Subscribe to poll responses
        liveStream.pubSub.subscribe(POLL_RESPONSE_TOPIC, responsesListener);
    }
    private void updateResultBars() {
        // Clear previous results
        if (optionsContainer != null) {
            optionsContainer.removeAllViews();
        }
        // Create result bars for each option
        for (Map.Entry<String, Integer> entry : pollResults.entrySet()) {
            String option = entry.getKey();
            int votes = entry.getValue();
            int percentage = (totalVotes > 0) ? (votes * 100) / totalVotes : 0;
            // Create progress bar UI showing percentage
            // ... UI code to display results ...
        }
    }
}
API Reference
The API references for all the methods and events utilized in this guide are provided below.
Got a Question? Ask us on discord

