Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yospace connector #20

Merged
merged 71 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
653bf40
Add yospace module
MattiasBuelens May 22, 2024
2f0263f
Add dependency on Yospace Ad Management SDK
MattiasBuelens May 22, 2024
d964cf6
Add basic YospaceConnector
MattiasBuelens May 27, 2024
643ab50
Store session only when successful
MattiasBuelens May 27, 2024
c9d134c
Add AnalyticEventObserver support
MattiasBuelens May 27, 2024
41a1622
Serialize YospaceSsaiDescription
MattiasBuelens May 27, 2024
b29ec09
Test serialization
MattiasBuelens May 27, 2024
cd375e8
Simplify
MattiasBuelens May 27, 2024
41b9ded
Report player events to Yospace
MattiasBuelens May 28, 2024
db86f88
Report timed metadata to Yospace
MattiasBuelens May 28, 2024
72771b8
Move SerializedSessionProperties to separate file
MattiasBuelens May 29, 2024
7509fb4
Make internal
MattiasBuelens May 29, 2024
16e8cf1
Add SessionProperties.copy()
MattiasBuelens May 29, 2024
947e50c
Set default user agent for Yospace session
MattiasBuelens May 29, 2024
9a819d2
Use lateinit for connectors in sample app
MattiasBuelens May 29, 2024
52be66d
Reformat
MattiasBuelens May 29, 2024
2c1d949
Add yospaceVersion to gradle.properties
MattiasBuelens May 29, 2024
9402eaa
Update YospaceSsaiDescription to latest API
MattiasBuelens May 29, 2024
ebeb131
Add source select dialog to sample app
MattiasBuelens May 29, 2024
92dfd2b
Improve type in NielsenHandler
MattiasBuelens May 29, 2024
9024825
Add YospaceSsaiDescription.Builder
MattiasBuelens May 29, 2024
68f6790
Add Yospace connector to sample app
MattiasBuelens May 29, 2024
0f1311e
Add Yospace test sources to sample app
MattiasBuelens May 29, 2024
6b2f62a
Extract finishReport helper
MattiasBuelens May 29, 2024
20a2892
Fix incorrect metadata
MattiasBuelens May 29, 2024
c6e7771
Report playhead updates
MattiasBuelens May 29, 2024
0dd1734
Fix currentPlayhead for DVRLive sessions
MattiasBuelens May 29, 2024
430d599
Add Yospace ads and ad breaks to THEOplayer
MattiasBuelens May 29, 2024
e189600
Tweaks
MattiasBuelens May 29, 2024
e00c3a1
Refactor
MattiasBuelens May 29, 2024
01002b4
Convert timed metadata timestamps to playhead
MattiasBuelens May 29, 2024
a3d7867
Make internal
MattiasBuelens May 29, 2024
6f45802
Fix Yospace module name in Dokka
MattiasBuelens May 29, 2024
c26e90f
Tweak
MattiasBuelens May 29, 2024
9ca82c4
Remove unnecessary @Serializable
MattiasBuelens May 29, 2024
1882403
Tweak
MattiasBuelens May 29, 2024
6788f49
Rework stream start computation
MattiasBuelens May 29, 2024
bf82fbd
Fix permissions in sample app
MattiasBuelens May 29, 2024
72a2a26
Log ad events in sample app
MattiasBuelens May 29, 2024
95def4c
Use timed metadata only for live playback
MattiasBuelens May 29, 2024
6c4a6fe
Remove listeners once streamStart is known
MattiasBuelens May 29, 2024
6332413
Tweak
MattiasBuelens May 29, 2024
95798a2
Handle ad breaks without information during live playback
MattiasBuelens May 29, 2024
9ac0c15
Remove ad.timeOffset, since we always create an ad break
MattiasBuelens May 29, 2024
a5bdd3c
Convert AdBreak.timeOffset from playhead time
MattiasBuelens May 30, 2024
9364f47
Fix Ad.skipOffset
MattiasBuelens May 30, 2024
c6790a4
Require THEOplayerView in YospaceConnector
MattiasBuelens May 30, 2024
73136a2
Tweak gradle.properties
MattiasBuelens May 30, 2024
45ad962
Add ads UI
MattiasBuelens May 30, 2024
e3ae28e
Pause player before opening clickthrough
MattiasBuelens May 31, 2024
a857990
Show non-linears in UI
MattiasBuelens May 31, 2024
7c2fb77
Run YospaceUiHandler methods on UI thread
MattiasBuelens May 31, 2024
df9d05a
Hide non-linears on ad end
MattiasBuelens May 31, 2024
4700ab0
Fix non-linear layout
MattiasBuelens May 31, 2024
d9ecdcc
Rename
MattiasBuelens May 31, 2024
7fe11eb
Add documentation
MattiasBuelens May 31, 2024
ed5ccf5
Add sample code
MattiasBuelens May 31, 2024
b77c525
Reformat
MattiasBuelens May 31, 2024
a9a8e6f
Rename
MattiasBuelens May 31, 2024
010b39f
Fix visibility
MattiasBuelens May 31, 2024
d8b9093
Move INTEGRATION_ID to static
MattiasBuelens Jun 3, 2024
150a936
Tweaks
MattiasBuelens Jun 3, 2024
2c12c23
Improve sample
MattiasBuelens Jun 3, 2024
ac7e33b
Add readme
MattiasBuelens Jun 3, 2024
230ca17
Fix CI
MattiasBuelens Jun 7, 2024
a644501
Tweak
MattiasBuelens Jun 11, 2024
5025865
Handle app moving to the background
MattiasBuelens Jun 11, 2024
8f0d205
Fix sample app
MattiasBuelens Jun 11, 2024
3d99f3c
Add `@JvmOverloads` to YospaceSsaiDescription constructor
MattiasBuelens Jun 12, 2024
768929c
Add instructions on installing the Ad Management SDK
MattiasBuelens Jun 12, 2024
5bf6b92
Add new line
georgechoustoulakis Jun 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ jobs:
uses: gradle/actions/setup-gradle@v3
- name: Run unit tests
run: ./gradlew testReleaseUnitTest
env:
YOSPACE_USERNAME: ${{ secrets.YOSPACE_USERNAME }}
YOSPACE_PASSWORD: ${{ secrets.YOSPACE_PASSWORD }}
3 changes: 3 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ jobs:
uses: gradle/actions/setup-gradle@v3
- name: Build API documentation with Dokka
run: ./gradlew :dokkaHtmlMultiModule --no-configuration-cache
env:
YOSPACE_USERNAME: ${{ secrets.YOSPACE_USERNAME }}
YOSPACE_PASSWORD: ${{ secrets.YOSPACE_PASSWORD }}
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPOSILITE_USERNAME: ${{ secrets.REPOSILITE_USERNAME }}
REPOSILITE_PASSWORD: ${{ secrets.REPOSILITE_PASSWORD }}
YOSPACE_USERNAME: ${{ secrets.YOSPACE_USERNAME }}
YOSPACE_PASSWORD: ${{ secrets.YOSPACE_PASSWORD }}
3 changes: 3 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ android {
defaultConfig {
applicationId "com.theoplayer.android.connector"
minSdk 21
targetSdk 34
versionCode 1
versionName "1.0"
}
Expand Down Expand Up @@ -47,4 +48,6 @@ dependencies {
implementation "com.nielsenappsdk.global:ad:9.2.0.0"
implementation project(':connectors:analytics:comscore')
implementation "com.comscore:android-analytics:$comscoreVersion"
implementation project(':connectors:yospace')
implementation "com.yospace:admanagement-sdk:$yospaceVersion"
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<application
android:allowBackup="true"
Expand Down
101 changes: 77 additions & 24 deletions app/src/main/java/com/theoplayer/android/connector/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
package com.theoplayer.android.connector

import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.FrameLayout
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.theoplayer.android.api.THEOplayerConfig
import com.theoplayer.android.api.THEOplayerView
import com.theoplayer.android.api.ads.LinearAd
import com.theoplayer.android.api.ads.ima.GoogleImaIntegrationFactory
import com.theoplayer.android.api.source.SourceDescription
import com.theoplayer.android.api.source.TypedSource
import com.theoplayer.android.api.source.addescription.GoogleImaAdDescription
import com.theoplayer.android.api.source.metadata.MetadataDescription
import com.theoplayer.android.connector.analytics.conviva.ConvivaConfiguration
import com.theoplayer.android.connector.analytics.conviva.ConvivaConnector
import com.theoplayer.android.connector.analytics.nielsen.NielsenConnector
import com.theoplayer.android.api.event.ads.AdBreakEvent
import com.theoplayer.android.api.event.ads.AdsEventTypes
import com.theoplayer.android.api.event.ads.SingleAdEvent
import com.theoplayer.android.connector.analytics.comscore.ComscoreConfiguration
import com.theoplayer.android.connector.analytics.comscore.ComscoreConnector
import com.theoplayer.android.connector.analytics.comscore.ComscoreMediaType
import com.theoplayer.android.connector.analytics.comscore.ComscoreMetaData
import com.theoplayer.android.connector.analytics.conviva.ConvivaConfiguration
import com.theoplayer.android.connector.analytics.conviva.ConvivaConnector
import com.theoplayer.android.connector.analytics.nielsen.NielsenConnector
import com.theoplayer.android.connector.yospace.YospaceConnector

const val TAG = "MainActivity"

class MainActivity : AppCompatActivity() {

private lateinit var theoplayerView: THEOplayerView
private var convivaConnector: ConvivaConnector? = null
private var nielsenConnector: NielsenConnector? = null
private lateinit var convivaConnector: ConvivaConnector
private lateinit var nielsenConnector: NielsenConnector
private lateinit var comscoreConnector: ComscoreConnector
private lateinit var yospaceConnector: YospaceConnector
private var selectedSource: Source = sources.first()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -37,6 +44,8 @@ class MainActivity : AppCompatActivity() {
setupConviva()
setupComscore()
setupNielsen()
setupYospace()
setupListeners()
}

private fun setupComscore() {
Expand Down Expand Up @@ -130,21 +139,65 @@ class MainActivity : AppCompatActivity() {
nielsenConnector = NielsenConnector(applicationContext, theoplayerView.player, appId, true)
}

fun setSource(view: View) {
theoplayerView.player.source = SourceDescription.Builder(
TypedSource.Builder("https://cdn.theoplayer.com/video/big_buck_bunny/big_buck_bunny.m3u8")
.build()
private fun setupYospace() {
yospaceConnector = YospaceConnector(theoplayerView)
}

private fun setupListeners() {
val ads = theoplayerView.player.ads
ads.addEventListener(AdsEventTypes.ADD_AD, ::onAdEvent)
ads.addEventListener(AdsEventTypes.AD_BEGIN, ::onAdEvent)
ads.addEventListener(AdsEventTypes.AD_END, ::onAdEvent)
ads.addEventListener(AdsEventTypes.AD_SKIP, ::onAdEvent)
ads.addEventListener(AdsEventTypes.AD_FIRST_QUARTILE, ::onAdEvent)
ads.addEventListener(AdsEventTypes.AD_MIDPOINT, ::onAdEvent)
ads.addEventListener(AdsEventTypes.AD_THIRD_QUARTILE, ::onAdEvent)
ads.addEventListener(AdsEventTypes.ADD_AD_BREAK, ::onAdBreakEvent)
ads.addEventListener(AdsEventTypes.AD_BREAK_BEGIN, ::onAdBreakEvent)
ads.addEventListener(AdsEventTypes.AD_BREAK_END, ::onAdBreakEvent)
ads.addEventListener(AdsEventTypes.AD_BREAK_CHANGE, ::onAdBreakEvent)
ads.addEventListener(AdsEventTypes.REMOVE_AD_BREAK, ::onAdBreakEvent)
}

fun onAdBreakEvent(event: AdBreakEvent<*>) {
val adBreak = event.adBreak
Log.d(
TAG,
"${event.type} - " +
"timeOffset=${adBreak.timeOffset}, ads=${adBreak.ads.size}," +
" maxDuration=${adBreak.maxDuration}," +
" currentTime=${theoplayerView.player.currentTime}"
)
}

fun onAdEvent(event: SingleAdEvent<*>) {
val ad = event.ad ?: return
Log.d(
TAG,
"${event.type} - " +
"id=${ad.id}, type=${ad.type}, adBreak.timeOffset=${ad.adBreak?.timeOffset}," +
(if (ad is LinearAd) " duration=${ad.duration}," else "") +
" currentTime=${theoplayerView.player.currentTime}"
)
.ads(
GoogleImaAdDescription.Builder("https://cdn.theoplayer.com/demos/ads/vast/dfp-linear-inline-no-skip.xml")
.timeOffset("5")
.build()
).metadata(MetadataDescription(mapOf("title" to "BigBuckBunny with Google IMA ads")))
.build()
nielsenConnector?.updateMetadata(hashMapOf(
"assetid" to "C112233",
"program" to "BigBuckBunny with Google IMA ads"
))
}

fun selectSource(view: View) {
val sourceNames = sources.map { it.name }.toTypedArray()
val selectedIndex = sources.indexOf(selectedSource)
AlertDialog.Builder(this)
.setTitle("Select source")
.setSingleChoiceItems(sourceNames, selectedIndex) { dialog, which ->
setSource(sources[which])
dialog.dismiss()
}
.create()
.show()
}

private fun setSource(source: Source) {
selectedSource = source
theoplayerView.player.source = source.sourceDescription
nielsenConnector.updateMetadata(source.nielsenMetadata)
}

fun playPause(view: View) {
Expand Down Expand Up @@ -177,4 +230,4 @@ class MainActivity : AppCompatActivity() {
super.onDestroy()
theoplayerView.onDestroy()
}
}
}
104 changes: 104 additions & 0 deletions app/src/main/java/com/theoplayer/android/connector/Sources.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.theoplayer.android.connector

import com.theoplayer.android.api.source.SourceDescription
import com.theoplayer.android.api.source.SourceType
import com.theoplayer.android.api.source.TypedSource
import com.theoplayer.android.api.source.addescription.GoogleImaAdDescription
import com.theoplayer.android.api.source.metadata.MetadataDescription
import com.theoplayer.android.connector.yospace.YospaceSsaiDescription
import com.theoplayer.android.connector.yospace.YospaceStreamType

data class Source(
val name: String,
val sourceDescription: SourceDescription,
val nielsenMetadata: HashMap<String, Any> = hashMapOf()
)

val sources: List<Source> by lazy {
listOf(
Source(
name = "BigBuckBunny with Google IMA ads",
sourceDescription = SourceDescription
.Builder(
TypedSource.Builder("https://cdn.theoplayer.com/video/big_buck_bunny/big_buck_bunny.m3u8")
.build()
)
.ads(
GoogleImaAdDescription.Builder("https://cdn.theoplayer.com/demos/ads/vast/dfp-linear-inline-no-skip.xml")
.timeOffset("5")
.build()
)
.metadata(MetadataDescription(mapOf("title" to "BigBuckBunny with Google IMA ads")))
.build(),
nielsenMetadata = hashMapOf(
"assetid" to "C112233",
"program" to "BigBuckBunny with Google IMA ads"
)
),
Source(
name = "Yospace HLS VOD",
sourceDescription = SourceDescription
.Builder(
TypedSource.Builder(
"https://csm-e-sdk-validation.bln1.yospace.com/csm/access/156611618/c2FtcGxlL21hc3Rlci5tM3U4?yo.av=4"
)
.type(SourceType.HLS)
.ssai(YospaceSsaiDescription(streamType = YospaceStreamType.VOD))
.build()
)
.build()
),
Source(
name = "Yospace HLS Live",
sourceDescription = SourceDescription
.Builder(
TypedSource.Builder(
"https://csm-e-sdk-validation.bln1.yospace.com/csm/extlive/yospace02,hlssample42.m3u8?yo.br=true&yo.av=4"
)
.type(SourceType.HLS)
.ssai(YospaceSsaiDescription(streamType = YospaceStreamType.LIVE))
.build()
)
.build()
),
Source(
name = "Yospace HLS DVRLive",
sourceDescription = SourceDescription
.Builder(
TypedSource.Builder(
"https://csm-e-sdk-validation.bln1.yospace.com/csm/extlive/yospace02,hlssample42.m3u8?yo.br=true&yo.lp=true&yo.av=4"
)
.type(SourceType.HLS)
.ssai(YospaceSsaiDescription(streamType = YospaceStreamType.LIVEPAUSE))
.build()
)
.build()
),
Source(
name = "Yospace DASH Live",
sourceDescription = SourceDescription
.Builder(
TypedSource.Builder(
"https://csm-e-sdk-validation.bln1.yospace.com/csm/extlive/yosdk01,t2-dash.mpd?yo.br=true&yo.av=4"
)
.type(SourceType.DASH)
.ssai(YospaceSsaiDescription(streamType = YospaceStreamType.LIVE))
.build()
)
.build()
),
Source(
name = "Yospace DASH DVRLive",
sourceDescription = SourceDescription
.Builder(
TypedSource.Builder(
"https://csm-e-sdk-validation.bln1.yospace.com/csm/extlive/yosdk01,dash.mpd?yo.br=true&yo.lp=true&yo.jt=1000&yo.av=4"
)
.type(SourceType.DASH)
.ssai(YospaceSsaiDescription(streamType = YospaceStreamType.LIVEPAUSE))
.build()
)
.build()
)
)
}
2 changes: 1 addition & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="set source"
android:onClick="setSource"/>
android:onClick="selectSource"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ plugins {
id 'com.android.library' version '8.4.1' apply false
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
id 'org.jetbrains.dokka' version '1.9.20'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.22' apply false
}

tasks.register('updateVersion') {
Expand Down
Loading