Trouble playing vid pre-roll ad in Roku

2019-09-15 01:08发布

问题:

I'm trying to add VAST video pre-roll ads to the SThree sample Roku SDK project (the "Simple Grid with Video and Details page (.zip)" version).

I can get it to work on app start by putting the following code into main.brs:

library "Roku_Ads.brs"
...
Sub RunUserInterface()
    ...
    raf = Roku_Ads() 
    raf.setAdPrefs(false)       'disable back-filled ads
    raf.setDebugOutput(true)
    raf.setAdUrl("http://pubads.g.doubleclick.net/gampad/ads?slotname=/82114269/Video/fallbacktest&sz=1920x1080&url=[http://roku.com&unviewed_position_start=1&output=vast&impl=s&env=vp&gdfp_req=1&ad_rule=0&description_url=http%3A%2F%2Fapps.roku.com&vad_type=linear&sdkv=roku&min_ad_duration=0&max_ad_duration=60000&rdid=ROKU_ADS_TRACKING_ID&is_lat=ROKU_ADS_LIMIT_TRACKING&idtype=rida&correlator=ROKU_ADS_TIMESTAMP&scor=ROKU_ADS_TIMESTAMP&pod=POD_NUM&ppos=POD_POSITION&cust_params=genre%3DROKU_ADS_CONTENT_GENRE%26ua%3DROKU_ADS_USER_AGENT%26ai%3DROKU_ADS_APP_ID]http://roku.com&unviewed_position_start=1&output=vast&impl=s&env=vp&gdfp_req=1&ad_rule=0&description_url=http%3A%2F%2Fapps.roku.com&vad_type=linear&sdkv=roku&min_ad_duration=0&max_ad_duration=60000&rdid=ROKU_ADS_TRACKING_ID&is_lat=ROKU_ADS_LIMIT_TRACKING&idtype=rida&correlator=ROKU_ADS_TIMESTAMP&scor=ROKU_ADS_TIMESTAMP&pod=POD_NUM&ppos=POD_POSITION&cust_params=genre%3DROKU_ADS_CONTENT_GENRE%26ua%3DROKU_ADS_USER_AGENT%26ai%3DROKU_ADS_APP_ID") 
    adPods = raf.getAds()
    shouldPlayContent = raf.showAds(adPods)

I however don't want to play an ad on startup, I want to play an ad before a video play. So I figure I can just add the lines above to components/screens/DetailsScreen/DetailsScreen.brs:

' on Button press handler
Sub onItemSelected()
    ' first button is Play
    if m.top.itemSelected = 0
        'START ADDING FOR PRE-ROLL
        raf = Roku_Ads() 
        raf.setAdPrefs(false)       'disable back-filled ads
        raf.setDebugOutput(true)
        raf.setAdUrl("http://pubads.g.doubleclick.net/gampad/ads?slotname=/82114269/Video/fallbacktest&sz=1920x1080&url=[http://roku.com&unviewed_position_start=1&output=vast&impl=s&env=vp&gdfp_req=1&ad_rule=0&description_url=http%3A%2F%2Fapps.roku.com&vad_type=linear&sdkv=roku&min_ad_duration=0&max_ad_duration=60000&rdid=ROKU_ADS_TRACKING_ID&is_lat=ROKU_ADS_LIMIT_TRACKING&idtype=rida&correlator=ROKU_ADS_TIMESTAMP&scor=ROKU_ADS_TIMESTAMP&pod=POD_NUM&ppos=POD_POSITION&cust_params=genre%3DROKU_ADS_CONTENT_GENRE%26ua%3DROKU_ADS_USER_AGENT%26ai%3DROKU_ADS_APP_ID]http://roku.com&unviewed_position_start=1&output=vast&impl=s&env=vp&gdfp_req=1&ad_rule=0&description_url=http%3A%2F%2Fapps.roku.com&vad_type=linear&sdkv=roku&min_ad_duration=0&max_ad_duration=60000&rdid=ROKU_ADS_TRACKING_ID&is_lat=ROKU_ADS_LIMIT_TRACKING&idtype=rida&correlator=ROKU_ADS_TIMESTAMP&scor=ROKU_ADS_TIMESTAMP&pod=POD_NUM&ppos=POD_POSITION&cust_params=genre%3DROKU_ADS_CONTENT_GENRE%26ua%3DROKU_ADS_USER_AGENT%26ai%3DROKU_ADS_APP_ID") 
        adPods = raf.getAds()
        shouldPlayContent = raf.showAds(adPods)
        'END ADDING FOR PRE-ROLL

        if shouldPlayContent
            m.videoPlayer.visible = true
            m.videoPlayer.setFocus(true)
            m.videoPlayer.control = "play"
            m.videoPlayer.observeField("state", "OnVideoPlayerStateChange")
        end if
    end if
End Sub

When I run this I get an error:

Roku_Ads Framework version 1.8
BRIGHTSCRIPT: ERROR: roAppInfo: class PLUGIN|MARKUP on thread RENDER: roku_ads_lib:/Roku_Ads.brs(527)
'Dot' Operator attempted with invalid BrightScript Component or interface reference. (runtime error &hec) in roku_ads_lib:/Roku_Ads.brs(528)
528: ??
Backtrace:
#4  Function roku_ads_util_getappid(key_ As String) As String
   file/line: roku_ads_lib:/Roku_Ads.brs(528)
#3  Function roku_ads_checkallowedfeature(keytype_ As String, util_ As Object) As Boolean
   file/line: roku_ads_lib:/Roku_Ads.brs(1287)
#2  Function roku_ads_constructor() As Object
   file/line: roku_ads_lib:/Roku_Ads.brs(264)
#1  Function roku_ads() As Object
   file/line: roku_ads_lib:/Roku_Ads.brs(32)
#0  Function onitemselected() As Void
   file/line: pkg:/components/screens/DetailsScreen/DetailsScreen.brs(75)

What am I doing wrong here? Can you not play an ad when a method is called from a onChange="onItemSelected" in the component.xml?

Update: Eugene's answer below is correct, Here is how I solved the problem:

Read about scene graph threads, events and handling application events. Once that is done read this post on passing data between the Render thread and main thread. You will need to understand scene graph data scoping.

Essentially you observe the itemSelected field in components/screens/DetailsScreen/DetailsScreen.xml:

m.DetailsScreen = scene.findNode("DetailsScreen")
m.DetailsScreen.observeField("itemSelected", m.port)

Then in your main threads event loop you handle the roSGNodeEvent:

while true
    msg = wait(0, m.port)        
    msgType = type(msg)

    ? ">>>Main Thread Msg: ";msgType

    if msgType = "roSGScreenEvent"
        if msg.isScreenClosed() then return
    else if msgType = "roSGNodeEvent"
        fieldName = msg.getField()
        fieldData = msg.getData()
        ? "> node: "; msg.getNode()
        ? "> field name: "; fieldName
        ? "> data: "; fieldData

        if (fieldName = "itemSelected" and fieldData = 0)   'User pressed play
            'wait for 0.5 second before proceeding to RAF
            sleep(500)
            PlayAd()
        endif
    end if
end while

PlayAd() sets m.DetailsScreen.videoPlayerVisible = true IF there was no ad or if ad finished playing. This causes onVideoVisibleChange to be invoked in components/screens/DetailsScreen/DetailsScreen.brs

回答1:

You can't use RAF in Render thread. You have to send event to the Main thread and and show ads there. You can find samples of RAF integration in Scene Graph here. More info on threads in Scene Graph can be found here.