Lock Screen and Control Center media controls 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
Lock Screen and Control Center media controls in mobile app
Medium
from 1 business day to 3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • 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
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Implementing Lock Screen and Control Center Media Controls

Media controls on lock screen — not optional feature but expected standard for any media player. Without them, user forced to unlock phone, find app and press pause instead of doing this with one tap right on Lock Screen.

iOS: MPNowPlayingInfoCenter and MPRemoteCommandCenter

Two independent objects: first handles metadata (what to show), second — commands (what to do on button click).

// Metadata
var nowPlayingInfo: [String: Any] = [:]
nowPlayingInfo[MPMediaItemPropertyTitle] = track.title
nowPlayingInfo[MPMediaItemPropertyArtist] = track.artist
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player.currentTime().seconds
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = track.duration
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate // 0.0 pause, 1.0 play

// Artwork — load image asynchronously
let artwork = MPMediaItemArtwork(boundsSize: CGSize(width: 300, height: 300)) { size in
    return self.trackArtworkImage ?? UIImage(named: "placeholder")!
}
nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork

MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo

MPNowPlayingInfoPropertyElapsedPlaybackTime — current position in track. If not update on seek, Lock Screen progress bar diverges from reality. Update after each seek and every 5–10 seconds via timer.

// Commands
let commandCenter = MPRemoteCommandCenter.shared()

commandCenter.playCommand.addTarget { [weak self] _ in
    self?.player.play()
    return .success
}
commandCenter.pauseCommand.addTarget { [weak self] _ in
    self?.player.pause()
    return .success
}
commandCenter.nextTrackCommand.addTarget { [weak self] _ in
    self?.playNext()
    return .success
}
commandCenter.changePlaybackPositionCommand.isEnabled = true
commandCenter.changePlaybackPositionCommand.addTarget { [weak self] event in
    guard let e = event as? MPChangePlaybackPositionCommandEvent else { return .commandFailed }
    self?.player.seek(to: CMTime(seconds: e.positionTime, preferredTimescale: 600))
    return .success
}

changePlaybackPositionCommand — slider on Lock Screen. Without it, user can't seek without opening app.

Commands need enable/disable by context: if playlist has one track — commandCenter.nextTrackCommand.isEnabled = false.

Android: MediaSession and MediaNotification

val mediaSession = MediaSession.Builder(context, player)
    .setCallback(object : MediaSession.Callback {
        override fun onConnect(session: MediaSession, controller: MediaSession.ControllerInfo) =
            MediaSession.ConnectionResult.accept(
                SessionCommands.EMPTY,
                Player.Commands.Builder().addAllCommands().build()
            )
    })
    .build()

media3 automatically creates notification with media controls when using MediaSessionService. Customize buttons via DefaultMediaNotificationProvider:

class CustomNotificationProvider(context: Context) : DefaultMediaNotificationProvider(context) {
    override fun getMediaButtons(
        session: MediaSession, playerCommands: Player.Commands,
        customLayout: ImmutableList<CommandButton>, showPauseButton: Boolean
    ): ImmutableList<CommandButton> {
        // Add "Favorite" button next to play/pause
        return super.getMediaButtons(session, playerCommands, customLayout, showPauseButton)
            .toMutableList().apply { add(favoriteButton) }.toImmutableList()
    }
}

Artwork in notification: MediaMetadata.Builder().setArtworkUri(uri).build() — system loads image by URI. To avoid ANR on network artwork load — pre-load via Coil or Glide in CoroutineScope(Dispatchers.IO), pass ready Bitmap via setArtworkData.

Flutter

audio_service (pub.dev) — standard package. Create AudioHandler, register in AudioService.init(). Command handlers: onPlay, onPause, onSkipToNext, onSeekTo. Metadata — mediaItem in AudioHandler.

Timeline

Media controls on iOS — 1 day (entire scope — setup two objects and metadata update). Android with custom notification — 1.5 days. Flutter — 1–2 days.