Skip to content

Commit

Permalink
Merge pull request #20 from THEOplayer/yospace
Browse files Browse the repository at this point in the history
Yospace connector
  • Loading branch information
georgechoustoulakis authored Jun 18, 2024
2 parents 2a1ce4c + 5bf6b92 commit ea876e5
Show file tree
Hide file tree
Showing 36 changed files with 1,729 additions and 39 deletions.
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

0 comments on commit ea876e5

Please sign in to comment.