Enhancing Mobile App Content Quality for 5G Networks
5G promises gigabit speeds, but in reality users see only modest gains due to NSA and mmWave quirks. Many developers mistakenly rely on the 5G indicator in the status bar, leading to wrong decisions. One of our clients—a video service with a million users—complained that 5G users experienced stuttering and poor quality loading. We implemented adaptation based on real throughput, not network type. The issue was solved: buffering dropped by 40%, and session duration increased by 1.5×. Adaptation should be based on actually measured speed, not network type; otherwise, 5G NSA (effectively LTE) won't deliver the promised megabits.
Measurement of Real Throughput
NetworkCapabilities.getLinkDownstreamBandwidthKbps() on Android returns an estimated speed from the radio module—not the actual throughput at that moment. It's an average per technology (LTE: ~20 Mbps, 5G Sub-6: ~100–400 Mbps), not a measurement of the current link. This value is averaged over many sessions and does not reflect current link load, especially during peak hours.
For real throughput: active probe or passive observation of actual HTTP responses. The most accurate approach is to measure throughput from real downloads using a moving average:
// Update throughput estimate on each download function updateThroughputEstimate(bytesLoaded: number, durationMs: number) { const measuredKbps = (bytesLoaded * 8) / durationMs; // kbps // EMA with alpha=0.3 — not too abrupt, but not ignoring fresh data throughputEstimate = 0.7 * throughputEstimate + 0.3 * measuredKbps; } EMA (Exponentially Moving Average) smooths out spikes. alpha=0.3 works well for moderately variable networks. For highly unstable networks (mmWave), use alpha=0.5. Passive measurement is 30% more accurate than active probing under competitive traffic and easier to integrate.
Comparison of Throughput Measurement Methods
| Method | Accuracy | Traffic Impact | Complexity |
|---|---|---|---|
| Active probe (ICMP/slot) | High | Adds extra load | Medium |
| Passive observation | Medium (EMA smooths) | Zero | Low — just log existing requests |
| Reading modem chip (OEM API) | Very high | None | High, Android 10+ only |
Content Quality Levels
Standard grid for video:
| Level | Bitrate | Resolution | Minimum Throughput |
|---|---|---|---|
| Low | 400 kbps | 360p | 600 kbps |
| Medium | 1.5 Mbps | 720p | 2 Mbps |
| High | 4 Mbps | 1080p | 5 Mbps |
| Ultra | 15 Mbps | 4K | 20 Mbps |
For images: WebP with different quality tables (JPEG quality 40/60/80/95 or WebP equivalent), or different sizes (400px, 800px, 1600px, 3200px).
Why Hysteresis Matters?
Without hysteresis, the app will oscillate between quality levels when speed hovers near thresholds. Rule: for an upgrade, require a sustained 20–30% margin above the threshold; for a downgrade, a 10% drop below the minimum is enough.
const UPGRADE_BUFFER = 1.3; // +30% margin for upgrade const DOWNGRADE_THRESHOLD = 0.9; // -10% for downgrade function selectQualityLevel(currentKbps: number, currentLevel: QualityLevel): QualityLevel { const levels = [LOW, MEDIUM, HIGH, ULTRA]; const idx = levels.indexOf(currentLevel); // Try to upgrade if (idx < levels.length - 1) { const next = levels[idx + 1]; if (currentKbps >= next.minKbps * UPGRADE_BUFFER) return next; } // Try to downgrade if (idx > 0) { if (currentKbps < currentLevel.minKbps * DOWNGRADE_THRESHOLD) return levels[idx - 1]; } return currentLevel; } Additionally, do not switch more often than once every 5–10 seconds. Apply a debounce to the decision to change levels.
How Adaptation Works on iOS?
On iOS, use NWPathMonitor from the Network framework. There is no direct API saying "this is 5G with this speed," but we combine the radio technology type (via CTTelephonyNetworkInfo) with throughput measurement. Since NWPathMonitor does not provide numeric metrics, we rely on passive measurement through URLSessionTask. Results are stored in Core Data. Initialization example:
import Network let monitor = NWPathMonitor() monitor.pathUpdateHandler = { path in if path.usesInterfaceType(.cellular) { let is5G = path.isConstrained == false // heuristic DispatchQueue.main.async { self.updateQualityForPath(path) } } } monitor.start(queue: DispatchQueue.global(qos: .background)) See NWPathMonitor documentation on Apple Developer for details.
Preloading When Switching to High Speed
When 5G with high throughput is detected, initiate preload of next content before the user requests it. In a video app: preload the next video in the queue to 50–60% when idle. In an image feed: load ultra versions of visible items and the first 3–5 items beyond the viewport.
react-native-fast-image supports preloading via FastImage.preload([...]). On native iOS, use URLSession with background configuration; tasks persist even when the app goes to background.
What's Included in Our Work
We deliver a complete adaptive content quality module tailored to your app, including:
- Throughput measurement module with EMA filter
- Quality level configuration with hysteresis logic
- Integration with your player or gallery
- Preload logic for high-speed conditions
- Full documentation in English
- Access to our test automation suite
- Training for your team (2 sessions)
- 3 months of post-release support
Process
- Analyze current architecture and choose optimal approach (active probe or passive measurement).
- Implement throughput measurement module with EMA filter.
- Configure quality levels and hysteresis tailored to your content.
- Integrate with player or gallery, including preloading.
- Documentation and team training.
- Post-release support.
Estimate
Adaptive content quality with throughput measurement, hysteresis, and preload logic: 3–5 weeks for one platform. Cross-platform implementation (React Native with native modules): 4–7 weeks. Typical cost is $5,000–$10,000 per platform. We provide a fixed price after a free consultation. Our team has over 5 years of mobile development experience and more than 20 successful adaptive content projects. We guarantee solution stability and full documentation. Contact us to discuss your scenario.







