Skip to content

Commit

Permalink
Avoid measuring video streaming in background (#425)
Browse files Browse the repository at this point in the history
  • Loading branch information
waliid committed Jun 20, 2023
1 parent a7b8cd1 commit 02a7be8
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 8 deletions.
12 changes: 12 additions & 0 deletions Sources/Analytics/ApplicationState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// Copyright (c) SRG SSR. All rights reserved.
//
// License information is available from the LICENSE file.
//

import Foundation

enum ApplicationState {
case foreground
case background
}
1 change: 0 additions & 1 deletion Sources/Analytics/ComScore/ComScoreService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ struct ComScoreService {
comScoreConfiguration.addClient(with: publisherConfiguration)

comScoreConfiguration.applicationVersion = applicationVersion
comScoreConfiguration.usagePropertiesAutoUpdateMode = .foregroundAndBackground
comScoreConfiguration.preventAdSupportUsage = true
comScoreConfiguration.addPersistentLabels([
"mp_brand": configuration.vendor.rawValue,
Expand Down
26 changes: 19 additions & 7 deletions Sources/Analytics/ComScore/ComScoreTracker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ComScore
import CoreMedia
import Foundation
import Player
import UIKit

/// A comScore tracker for streaming.
///
Expand All @@ -34,12 +35,17 @@ public final class ComScoreTracker: PlayerItemTracker {
}
.store(in: &cancellables)

Publishers.CombineLatest3(player.$playbackState, player.$isSeeking, player.$isBuffering)
.weakCapture(player)
.sink { [weak self] state, player in
self?.notify(playbackState: state.0, isSeeking: state.1, isBuffering: state.2, player: player)
}
.store(in: &cancellables)
Publishers.CombineLatest4(
UIApplication.shared.applicationStatePublisher(),
player.$playbackState,
player.$isSeeking,
player.$isBuffering
)
.weakCapture(player)
.sink { [weak self] state, player in
self?.notify(applicationState: state.0, playbackState: state.1, isSeeking: state.2, isBuffering: state.3, player: player)
}
.store(in: &cancellables)

player.objectWillChange
.receive(on: DispatchQueue.main)
Expand All @@ -59,12 +65,18 @@ public final class ComScoreTracker: PlayerItemTracker {
streamingAnalytics = SCORStreamingAnalytics()
}

private func notify(playbackState: PlaybackState, isSeeking: Bool, isBuffering: Bool, player: Player) {
// swiftlint:disable:next cyclomatic_complexity
private func notify(applicationState: ApplicationState, playbackState: PlaybackState, isSeeking: Bool, isBuffering: Bool, player: Player) {
guard !metadata.labels.isEmpty else { return }

AnalyticsListener.capture(streamingAnalytics.configuration())
streamingAnalytics.setProperties(for: player, streamType: metadata.streamType)

guard applicationState == .foreground else {
streamingAnalytics.notifyEvent(for: .paused, at: player.effectivePlaybackSpeed)
return
}

switch (isSeeking, isBuffering) {
case (true, true):
streamingAnalytics.notifySeekStart()
Expand Down
23 changes: 23 additions & 0 deletions Sources/Analytics/UIApplication.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Copyright (c) SRG SSR. All rights reserved.
//
// License information is available from the LICENSE file.
//

import Combine
import Core
import UIKit

extension UIApplication {
func applicationStatePublisher() -> AnyPublisher<ApplicationState, Never> {
Publishers.Merge(
NotificationCenter.default.weakPublisher(for: UIApplication.didEnterBackgroundNotification, object: self)
.map { _ in .background },
NotificationCenter.default.weakPublisher(for: UIApplication.didBecomeActiveNotification, object: self)
.map { _ in .foreground }
)
.prepend(applicationState == .background ? .background : .foreground)
.removeDuplicates()
.eraseToAnyPublisher()
}
}

0 comments on commit 02a7be8

Please sign in to comment.