Live Wallpapers 9 min read • Updated Sep 2026

How to Stream & Set 4K Live Video Wallpapers in Android & Flutter (MP4)

Learn how to consume NexWall Ultra 4K Live Video Wallpaper API, stream looping MP4 backgrounds, and configure Android WallpaperService and Flutter Video Player.

⚠️ Production Security Warning — Read Before Publishing to App Store

The code samples in this guide use a Bearer token directly in client-side mobile code. This is for local development and prototyping only. Any API key or Bearer token embedded inside a compiled Android APK or iOS IPA can be extracted in under 60 seconds using free tools like jadx-gui or apktool.

For production apps on Google Play / App Store, always use a backend proxy architecture:

Your Mobile App → Your Own Secure Backend → NexWall API

Your backend holds the NexWall Bearer token securely. It proxies requests from your app, adds auth, and returns responses — keeping your API key permanently hidden from reverse engineers. Read API Docs →

1. Consuming the Ultra Live Wallpaper Feed

Live wallpapers in NexWall are available in looping MP4 format via the Ultra API tier. Query live items with the type=live parameter:

GET https://nexwall.kodnextech.com/api/developer/v1/wallpapers?type=live&per_page=20
Authorization: Bearer YOUR_ULTRA_API_KEY

2. Android WallpaperService Implementation

import android.media.MediaPlayer
import android.service.wallpaper.WallpaperService
import android.view.SurfaceHolder

class VideoLiveWallpaperService : WallpaperService() {

    override fun onCreateEngine(): Engine = VideoEngine()

    inner class VideoEngine : Engine() {
        private var mediaPlayer: MediaPlayer? = null

        override fun onSurfaceCreated(holder: SurfaceHolder) {
            super.onSurfaceCreated(holder)
            mediaPlayer = MediaPlayer().apply {
                setSurface(holder.surface)
                // Stream from local cached MP4 file
                setDataSource(applicationContext, videoFileUri)
                isLooping = true
                setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING)
                prepare()
                start()
            }
        }

        override fun onVisibilityChanged(visible: Boolean) {
            if (visible) mediaPlayer?.start() else mediaPlayer?.pause()
        }

        override fun onSurfaceDestroyed(holder: SurfaceHolder) {
            mediaPlayer?.release()
            mediaPlayer = null
            super.onSurfaceDestroyed(holder)
        }
    }
}

Want to test this endpoint right now?

Use the interactive Live Sandbox Console to test queries without writing code.

Try In Sandbox