Live stream donations and gifts in mobile app

TRUETECH is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Live stream donations and gifts in mobile app
Medium
~5 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    757
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    874
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Implementing Donations and Gifts During Live Streaming in Mobile Apps

Donations in a stream aren't just payments. It's a real-time event: user sends a gift → animation flies over the video → viewers see the donor's name in the feed → streamer gets notified. Between the button press and animation appearance should be less than a second. This requires thoughtful integration: payment processor → backend → WebSocket → client.

Architecture: Three Parallel Streams

A donation flows through three independent layers simultaneously:

  1. Payment stream — charging via Stripe/IAP/Google Play Billing with confirmation
  2. Real-time stream — WebSocket event to all broadcast viewers
  3. Donation feed — UI counter update and log scroll

An error in one stream shouldn't block others. Gift animation shows after payment confirmation, not before.

Virtual Currency: Why Not Direct Payments

Most streaming apps use virtual currency (coins, crystals) instead of direct transactions:

  • App Store and Google Play take 30% on in-app purchases, but virtual currency splits the coin purchase (IAP) from coin spending (server logic) — deduction happens on the server, App Store isn't involved
  • User buys a coin pack via IAP, spends anytime — async from the payment flow
  • Small donor aggregation: sending 5 rubles directly is expensive due to fees, sending 5 pre-bought coins is cheap
// Purchase coins via Google Play Billing
val productDetails = // loaded via BillingClient.queryProductDetailsAsync

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                .setProductDetails(productDetails)
                .build()
        )
    )
    .build()

billingClient.launchBillingFlow(activity, billingFlowParams)

Gift Types: GiftItem Object

data class GiftItem(
    val id: String,
    val name: String,           // "Rose", "Rocket", "Crown"
    val coinCost: Int,          // cost in coins
    val animationUrl: String,   // Lottie JSON or MP4
    val displayDurationMs: Long // how long to show animation
)

Gift animations are Lottie (JSON, ~50-200 KB) or short MP4s (~500 KB). Lottie is preferable: scales without artifacts, supports transparency, doesn't require a media decoder.

Real-time: WebSocket Gift Event

After deducting coins on the server (atomic DB transaction) — publish an event to the broadcast's WebSocket channel:

{
  "type": "gift",
  "streamId": "stream-abc123",
  "senderId": "user-456",
  "senderName": "Alexey",
  "senderAvatar": "https://cdn.example.com/avatars/456.jpg",
  "giftId": "gift-rocket",
  "giftName": "Rocket",
  "coinAmount": 50,
  "timestamp": "2024-06-15T14:30:01.234Z"
}

The server must verify coin balance before publishing. Never trust the client: client says "send rocket for 50 coins" → server checks balance, deducts, then publishes the event. Not the other way.

Client: Animation Queue

Multiple viewers can send gifts simultaneously. Can't show all animations in parallel — the screen becomes chaos. Need a queue:

class GiftAnimationQueue {
    private var queue: [GiftEvent] = []
    private var isPlaying = false

    func enqueue(_ event: GiftEvent) {
        queue.append(event)
        if !isPlaying { playNext() }
    }

    private func playNext() {
        guard !queue.isEmpty else { isPlaying = false; return }
        isPlaying = true
        let event = queue.removeFirst()

        showGiftAnimation(event) { [weak self] in
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                self?.playNext()
            }
        }
    }

    private func showGiftAnimation(_ event: GiftEvent, completion: @escaping () -> Void) {
        let animationView = LottieAnimationView(name: event.giftId)
        animationView.frame = overlayView.bounds
        overlayView.addSubview(animationView)

        animationView.play { _ in
            animationView.removeFromSuperview()
            completion()
        }
    }
}

On Android, a similar queue using Lottie AnimationView and LinkedList<GiftEvent> with Handler.

Donation Feed: RecyclerView with Prepend

New donations are added to the list beginning, not end:

class DonationAdapter : RecyclerView.Adapter<DonationViewHolder>() {
    private val donations = mutableListOf<DonationItem>()

    fun prepend(donation: DonationItem) {
        donations.add(0, donation)
        notifyItemInserted(0)
        recyclerView.scrollToPosition(0)
    }
}

Handling Offline Viewers

Viewers can reconnect mid-stream. On reconnect, don't replay all missed animations — show only the donation log as text and last N events.

Top Donors: Real-time Aggregation

// Redis ZSET for top donors of the broadcast
// ZINCRBY stream:{streamId}:donations {coinAmount} {userId}
// ZREVRANGE stream:{streamId}:donations 0 9 WITHSCORES — top 10

Updates on each donation, broadcast to all viewers every 5–10 seconds via separate WebSocket channel.

Included in Work

  • Server-side coin deduction logic (atomic transaction)
  • WebSocket event broadcast to all viewers
  • Gift animation queue on client (Lottie)
  • Donation feed with prepend logic
  • Real-time top donors
  • Reconnect and state recovery handling

Timeline

5 days. Server-side with WebSocket and coin billing — 2 days. Client-side with animations and feed — 2 days. Integration, testing, edge cases — 1 day. Pricing is calculated individually.