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