IMA SDK ادغام تبلیغات چندرسانه ای را در وب سایت ها و برنامه های شما آسان می کند. IMA SDK میتواند از هر سرور تبلیغاتی سازگار با VAST آگهی درخواست کند و پخش آگهی را در برنامههای شما مدیریت کند. با IMA DAI SDK، برنامهها درخواست پخش جریانی برای آگهی و ویدیوی محتوا را ارائه میکنند - اعم از VOD یا محتوای زنده. سپس SDK یک جریان ویدیوی ترکیبی را برمیگرداند، به طوری که نیازی به مدیریت جابجایی بین آگهی و ویدیوی محتوا در برنامه خود ندارید.
راه حل DAI مورد علاقه خود را انتخاب کنید
این راهنما نشان میدهد که چگونه میتوان یک پخش زنده یا VOD را با استفاده از IMA DAI SDK برای Roku پخش کرد. برای مشاهده یا دنبال کردن یک نمونه ادغام کامل، نمونه Pod Serving را دانلود کنید.
نمای کلی سرویس IMA DAI Pod
اجرای Pod Serving با استفاده از IMA DAI شامل دو جزء اصلی SDK است که در این راهنما نشان داده شده است:
-
StreamRequest.createPodLiveStreamRequest()
/StreamRequest.createPodVodStreamRequest()
: یک شی ایجاد می کند که یک درخواست جریان را برای سرورهای تبلیغاتی Google تعریف می کند. این درخواست ها یک کد شبکه را مشخص می کنند و Pod Liveima.StreamRequest
همچنین به یک کلید دارایی سفارشی و یک کلید API اختیاری نیاز دارد. -
StreamManager
: شیای که ارتباط بین جریان ویدئو و IMA DAI SDK را کنترل میکند، مانند شلیک پینگهای ردیابی و ارسال رویدادهای جریان به ناشر.
علاوه بر این، باید درخواستی را به سرور دستکاری مانیفست خود ارسال کنید تا مانیفست جریان را برای نمایش برنامه شما بازیابی کند. فرآیند دقیق میتواند شریک فناوری ویدئو (VTP) را به VTP تغییر دهد.
پیش نیازها
- صفحه سازگاری ما را بخوانید تا مطمئن شوید مورد استفاده مورد نظر شما پشتیبانی می شود.
- کد پخش کننده نمونه Roku ما را دانلود کنید.
- کد پخش کننده نمونه را در دستگاه Roku مستقر کنید تا تأیید کنید که تنظیمات توسعه شما کار می کند.
ویدیوی خود را پخش کنید
پخش کننده ویدیوی نمونه ارائه شده یک ویدیوی محتوایی را خارج از جعبه پخش می کند. پخش کننده نمونه را در دستگاه Roku خود مستقر کنید تا مطمئن شوید که محیط توسعه شما به درستی تنظیم شده است.
پخش کننده ویدیوی خود را به یک پخش کننده جریانی IMA DAI تبدیل کنید
این مراحل را برای پیاده سازی پخش کننده استریم دنبال کنید.
Sdk.xml ایجاد کنید
یک فایل جدید به پروژه خود در کنار MainScene.xml
به نام Sdk.xml
اضافه کنید و boilerplate زیر را اضافه کنید:
Sdk.xml
<?xml version = "1.0" encoding = "utf-8" ?>
<component name = "imasdk" extends = "Task">
<interface>
</interface>
<script type = "text/brightscript">
<![CDATA[
' Your code goes here.
]]>
</script>
</component>
شما باید هر دوی این فایل ها ( MainScene.xml
و Sdk.xml
) را در سراسر این راهنما ویرایش کنید.
چارچوب IMA DAI SDK را بارگیری کنید
برای بارگیری چارچوب، موارد زیر را به manifest
و Sdk.xml
اضافه کنید:
آشکار
bs_libs_required=googleima3
Sdk.xml
<?xml version = "1.0" encoding = "utf-8" ?>
<component name = "imasdk" extends = "Task">
<interface>
</interface>
<script type = "text/brightscript">
<![CDATA[
Library "IMA3.brs"
]]>
</script>
</component>
IMA DAI SDK را راه اندازی کنید
اولین قدم برای بارگیری جریان درج آگهی پویا IMA، بارگیری و مقداردهی اولیه IMA DAI SDK است. زیر اسکریپت IMA DAI SDK را مقداردهی اولیه می کند.
Sdk.xml
<?xml version="1.0" encoding="utf-8" ?>
<component name="IMASDKTask" extends="Task">
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
</interface>
<script type = "text/brightscript">
<![CDATA[
Library "IMA3.brs"
sub init()
m.top.functionName = "runThread"
end sub
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
end sub
sub initializeIMASDK()
if m.sdk = invalid
m.sdk = New_IMASDK()
end if
m.top.IMASDKInitialized = true
end sub
]]>
</script>
</component>
اکنون این کار را در MainScene.xml
شروع کنید و تماس را حذف کنید تا جریان محتوا بارگیری شود.
MainScene.xml
<?xml version="1.0" encoding="utf-8" ?>
<component extends="Scene" initialFocus="myVideo" name="MainScene">
<script type="text/brightscript">
<![CDATA[
function init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
runIMASDKTask()
end function
function runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.IMASDKTask.control = "RUN"
end function
sub handleIMASDKInitialized()
' Follow your manifest manipulator (VTP) documentation to register a user
' streaming session if needed.
end sub
sub handleIMASDKErrors(message as object)
print "------ IMA DAI SDK failed ------"
if message <> invalid and message.getData() <> invalid
print "IMA DAI SDK Error ";message.getData()
end if
end sub
]]>
</script>
<children>
<Video height="720" id="myVideo" visible="false" width="1280"/>
</children>
</component>
یک پخش کننده جریان IMA ایجاد کنید
در مرحله بعد، باید از roVideoScreen
موجود خود برای ایجاد یک پخش کننده جریان IMA استفاده کنید.
پخش زنده پخش پاد
برای پخش جریانی زنده، این پخش کننده جریانی سه روش پاسخ به تماس را اجرا می کند: streamInitialized
، adBreakStarted
و adBreakEnded
.
همچنین هنگام بارگیری جریان، پخش ترفند را غیرفعال کنید. این کار باعث میشود که کاربران نتوانند در همان لحظه که شروع میشود، قبل از فعال شدن رویداد شروع شکستن آگهی، از پرش پرش کنند.
Sdk.xml
<?xml version="1.0" encoding="utf-8" ?>
<component name="IMASDKTask" extends="Task">
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
<field id="urlData" type="assocarray" />
<field id="adPlaying" type="Boolean" />
<field id="videoNode" type="Node" />
</interface>
<script type="text/brightscript">
...
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
end sub
...
sub initializeIMASDK()
if m.ima = invalid
ima = New_IMASDK()
ima.initSdk()
m.ima = ima
end if
m.top.IMASDKInitialized = true
end sub
sub setupPlayerCallbacks()
m.player = m.ima.createPlayer()
m.player.top = m.top
m.player.streamInitialized = function(urlData)
m.top.videoNode.enableTrickPlay = false
m.top.urlData = urlData
end function
m.player.adBreakStarted = function(adBreakInfo)
print "------ Ad break started ------"
m.top.adPlaying = true
m.top.videoNode.enableTrickPlay = false
end function
m.player.adBreakEnded = function(adBreakInfo)
print "------ Ad break ended ------"
m.top.adPlaying = false
m.top.videoNode.enableTrickPlay = true
end function
end sub
</script>
...
</component>
سرویس پاد استریم VOD
برای جریانهای VOD، این پخشکننده جریان چهار روش پاسخ به تماس را پیادهسازی میکند: streamInitialized
، loadUrl
، adBreakStarted
و adBreakEnded
. در streamInitialized
callback، مطمئن شوید که StreamManager.loadThirdPartyStream()
را فراخوانی کنید. عدم انجام این کار باعث می شود SDK عملکرد loadUrl
را راه اندازی نکند.
در این مرحله، شما همچنین یک URL جریان از شریک فناوری ویدیوی خود (VTP) با شناسه جریانی که در loadAdPodStream()
به دست آمده است درخواست می کنید. سپس، StreamManager.loadThirdPartyStream()
با مانیفست غلاف آگهی و هر زیرنویسی که توسط VTP شما برگردانده شده است، فراخوانی کنید.
همچنین هنگام بارگیری جریان، پخش ترفند را غیرفعال کنید. این کار باعث میشود که کاربران نتوانند در همان لحظه که شروع میشود، قبل از فعال شدن رویداد شروع شکستن آگهی، از پرش پرش کنند.
Sdk.xml
<?xml version="1.0" encoding="utf-8" ?>
<component name="IMASDKTask" extends="Task">
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
<field id="adStitchedStreamInfo" type="assocarray" />
<field id="adPlaying" type="Boolean" />
<field id="videoNode" type="Node" />
<field id="streamParameters" type="assocarray" />
</interface>
<script type="text/brightscript">
...
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
end sub
...
sub initializeIMASDK()
if m.ima = invalid
ima = New_IMASDK()
ima.initSdk()
m.ima = ima
end if
m.top.IMASDKInitialized = true
end sub
sub loadThirdPartyStream(adStitchedManifest as string, subtitleConfig as dynamic)
m.streamManager.loadThirdPartyStream(adStitchedManifest, subtitleConfig)
end sub
sub setupPlayerCallbacks()
m.player = m.ima.createPlayer()
m.player.top = m.top
m.player.streamInitialized = function(urlData)
adStitchedManifest = m.top.streamParameters.VTPManifest.replace("[[STREAMID]]", urlData.streamId)
loadThirdPartyStream(adStitchedManifest, m.top.streamParameters.subtitleConfig)
end function
m.player.loadUrl = function(streamInfo)
m.top.adStitchedStreamInfo = streamInfo
end function
m.player.adBreakStarted = function(adBreakInfo)
print "------ Ad break started ------"
m.top.adPlaying = true
m.top.videoNode.enableTrickPlay = false
end function
m.player.adBreakEnded = function(adBreakInfo)
print "------ Ad break ended ------"
m.top.adPlaying = false
m.top.videoNode.enableTrickPlay = true
end function
end sub
</script>
...
</component>
درخواست پخش زنده یا VOD Pod Serving را ایجاد و اجرا کنید
بعد از اینکه پخش کننده پخش جریانی داشتید، می توانید یک درخواست استریم ایجاد و اجرا کنید. این مثال دارای دادههایی برای یک جریان Pod Serving است که در m.testPodServingStream
ذخیره شده است.
پخش زنده پخش پاد
در شی m.testPodServingStream
، پارامترهایی را که Google Ad Manager برای شناسایی جریان مورد نظر نیاز دارد، مانند کد شبکه و کلید دارایی سفارشی ذخیره کنید. همچنین URL مانیفست مورد استفاده برای دسترسی به سرور دستکاری مانیفست خود را ذخیره کنید. در این مورد، URL مانیفست باید پس از بازگشت درخواست جریان، شناسه Google Stream را اضافه کند.
برای اینکه بتوانید از AdUI مانند نمادهای adChoices پشتیبانی کنید، باید به عنوان بخشی از درخواست خود، یک مرجع به گره حاوی ویدیوی محتوای خود ارسال کنید.
MainScene.xml
function init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
m.testPodServingStream = {
title: "Test live stream for DAI Pod Serving",
assetKey: "test-live-stream",
networkCode: "your-network-code",
manifest: "https://.../master.m3u8?stream_id=[[STREAMID]]",
apiKey: ""
}
runIMASDKTask()
end function
function runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.IMASDKTask.control = "RUN"
end function
Sdk.xml
<interface>
<field id="IMASDKInitialized" type="Boolean" />
<field id="errors" type="stringarray" />
<field id="urlData" type="assocarray" />
<field id="adPlaying" type="Boolean" />
<field id="videoNode" type="Node" />
<field id="streamParameters" type="assocarray" />
</interface>
...
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
end sub
sub loadAdPodStream()
request = m.ima.CreatePodLiveStreamRequest(m.top.streamParameters.assetKey, m.top.streamParameters.networkCode, m.top.streamParameters.apiKey)
' Set the player object so that the request can trigger the player's
' callbacks at stream initialization or playback events.
request.player = m.player
' Set the video node for the IMA DAI SDK to create ad UI as its child nodes.
request.adUiNode = m.top.video
requestResult = m.ima.requestStream(request)
if requestResult <> invalid
print "Error requesting stream ";requestResult
return
end if
m.streamManager = invalid
while m.streamManager = invalid
sleep(50)
m.streamManager = m.ima.getStreamManager()
end while
if m.streamManager = invalid
errors = CreateObject("roArray", 1, True)
invalidStreamManagerError = "Invalid stream manager"
print invalidStreamManagerError
errors.push(invalidStreamManagerError)
m.top.errors = errors
return
end if
if m.streamManager["type"] <> invalid and m.streamManager["type"] = "error"
errors = CreateObject("roArray", 1, True)
print "Stream request returns an error. " ; m.streamManager["info"]
errors.push(m.streamManager["info"])
m.top.errors = errors
return
end if
setupStreamManager()
m.streamManager.start()
end sub
سرویس پاد استریم VOD
در شی m.testPodServingStream
، کد شبکه مورد استفاده در درخواست جریان را ذخیره میکنید، بنابراین Google Ad Manager میتواند یک شناسه جریان ارائه دهد. همچنین URL مانیفست مورد استفاده برای دسترسی به مانیفست خاص کاربر را در سرور دستکاری مانیفست خود ذخیره کنید.
برای اینکه بتوانید از AdUI مانند نمادهای adChoices پشتیبانی کنید، باید به عنوان بخشی از درخواست خود، یک مرجع به گره حاوی ویدیوی محتوای خود ارسال کنید.
MainScene.xml
sub init()
m.video = m.top.findNode("myVideo")
m.video.notificationinterval = 1
m.testPodServingStream = {
title: "Pod Serving VOD Stream",
networkCode: "your-network-code",
VTPManifest: "https://.../manifest.m3u8?gam-stream-id=[[STREAMID]]",
subtitleConfig: []
}
runIMASDKTask()
end sub
sub runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.IMASDKTask.control = "RUN"
end sub
Sdk.xml
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
end sub
sub loadAdPodStream()
request = m.ima.CreatePodVodStreamRequest(m.top.streamParameters.networkCode)
' Set the player object so that the request can trigger the player
' callbacks at stream initialization or playback events.
request.player = m.player
' Set the video node for the IMA DAI SDK to create ad UI as its child nodes.
request.adUiNode = m.top.video
requestResult = m.ima.requestStream(request)
if requestResult <> invalid
print "Error requesting stream ";requestResult
return
end if
m.streamManager = invalid
while m.streamManager = invalid
sleep(50)
m.streamManager = m.ima.getStreamManager()
end while
if m.streamManager = invalid
errors = CreateObject("roArray", 1, True)
invalidStreamManagerError = "Invalid stream manager"
print invalidStreamManagerError
errors.push(invalidStreamManagerError)
m.top.errors = errors
return
end if
if m.streamManager["type"] <> invalid and m.streamManager["type"] = "error"
errors = CreateObject("roArray", 1, True)
print "Stream request returns an error. " ; m.streamManager["info"]
errors.push(m.streamManager["info"])
m.top.errors = errors
return
end if
setupStreamManager()
m.streamManager.start()
end sub
شنوندگان رویداد را اضافه کنید و جریان را شروع کنید
پخش زنده پخش پاد
پس از درخواست پخش جریانی خود، تنها چند کار باقی مانده است: افزودن شنوندگان رویداد برای ردیابی پیشرفت تبلیغات و ارسال پیامهای Roku به SDK. برای اطمینان از پخش صحیح تبلیغات، مهم است که همه پیامها را به SDK بازارسال کنید. عدم انجام این کار منجر به گزارش نادرست بازدیدهای تبلیغاتی می شود.
در این مرحله، شما همچنین یک تابع برای جایگزینی ماکرو [[STREAMID]]
با شناسه جریان اضافه میکنید و URL درخواست مانیفست تکمیلشده را به پخشکننده ویدیو ارسال میکنید. این پیاده سازی شناسه جریان را در این مرحله دریافت می کند، اما بسته به ادغام VTP شما، ممکن است قبل از این مرحله در دسترس باشد.
MainScene.xml
function runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.sdkTask.observeField("adStitchedStreamInfo", "loadAdStitchedStream")
m.sdkTask.control = "RUN"
end function
sub loadAdStitchedStream(message as object)
print "Ad pod stream information ";message
adPodStreamInfo = message.getData()
manifest = m.testPodservingStream.manifest.Replace("[[STREAMID]]", adPodStreamInfo.streamId)
playStream(manifest, adPodStreamInfo.format)
end sub
sub playStream(url as string, format as string)
vidContent = createObject("RoSGNode", "ContentNode")
vidContent.url = url
vidContent.title = m.testPodservingStream.title
vidContent.streamformat = format
m.video.content = vidContent
m.video.setFocus(true)
m.video.visible = true
m.video.control = "play"
m.video.EnableCookies()
end sub
Sdk.xml
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
if m.streamManager <> invalid
runLoop()
end if
end sub
sub runLoop()
m.top.videoNode.timedMetaDataSelectionKeys = ["*"]
' IMPORTANT: Failure to listen to the position and timedmetadata fields
' could result in ad impressions not being reported.
m.port = CreateObject("roMessagePort")
m.top.videoNode.observeField("position", m.port)
m.top.videoNode.observeField("timedMetaData", m.port)
m.top.videoNode.observeField("timedMetaData2", m.port)
m.top.videoNode.observeField("state", m.port)
while True
msg = wait(1000, m.port)
if m.top.videoNode = invalid
print "exiting"
exit while
end if
m.streamManager.onMessage(msg)
currentTime = m.top.videoNode.position
if currentTime > 3 And not m.top.adPlaying
m.top.videoNode.enableTrickPlay = true
end if
end while
end sub
sub setupStreamManager()
m.streamManager.addEventListener(m.sdk.AdEvent.ERROR, errorCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.START, startCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.FIRST_QUARTILE, firstQuartileCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.MIDPOINT, midpointCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.THIRD_QUARTILE, thirdQuartileCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.COMPLETE, completeCallback)
end sub
sub startCallback(ad as object)
print "Callback from SDK -- Start called - "
end sub
sub firstQuartileCallback(ad as object)
print "Callback from SDK -- First quartile called - "
end sub
sub midpointCallback(ad as object)
print "Callback from SDK -- Midpoint called - "
end sub
sub thirdQuartileCallback(ad as object)
print "Callback from SDK -- Third quartile called - "
end sub
sub completeCallback(ad as object)
print "Callback from SDK -- Complete called - "
end sub
function errorCallback(error as object)
print "Callback from SDK -- Error called - " ; error
m.errorState = True
end function
سرویس پاد استریم VOD
پس از درخواست پخش جریانی خود، تنها چند کار باقی مانده است: افزودن شنوندگان رویداد برای ردیابی پیشرفت تبلیغات و ارسال پیامهای Roku به SDK. برای اطمینان از پخش صحیح تبلیغات، مهم است که همه پیامها را به SDK بازارسال کنید. در صورت عدم انجام این کار، بازدیدهای تبلیغاتی به صورت نادرست گزارش می شوند.
MainScene.xml
sub runIMASDKTask()
m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
m.IMASDKTask.streamParameters = m.testPodservingStream
m.IMASDKTask.videoNode = m.video
m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
m.sdkTask.observeField("adStitchedStreamInfo", "loadAdStitchedStream")
m.sdkTask.control = "RUN"
end sub
sub loadAdStitchedStream(message as object)
print "Ad pod stream information ";message
adPodStreamInfo = message.getData()
end sub
sub playStream(url as string, format as string, subtitleConfig as object)
vidContent = createObject("RoSGNode", "ContentNode")
vidContent.title = m.testPodservingStream.title
vidContent.url = url
vidContent.subtitleConfig = subtitleConfig
vidContent.streamformat = format
m.video.content = vidContent
m.video.setFocus(true)
m.video.visible = true
m.video.control = "play"
m.video.EnableCookies()
end sub
Sdk.xml
sub runThread()
if not m.top.IMASDKInitialized
initializeIMASDK()
end if
setupPlayerCallbacks()
loadAdPodStream()
if m.streamManager <> invalid
runLoop()
end if
end sub
sub runLoop()
m.top.videoNode.timedMetaDataSelectionKeys = ["*"]
' IMPORTANT: Failure to listen to the position and timedmetadata fields
' could result in ad impressions not being reported.
m.port = CreateObject("roMessagePort")
m.top.videoNode.observeField("position", m.port)
m.top.videoNode.observeField("timedMetaData", m.port)
m.top.videoNode.observeField("timedMetaData2", m.port)
m.top.videoNode.observeField("state", m.port)
while True
msg = wait(1000, m.port)
if m.top.videoNode = invalid
exit while
end if
m.streamManager.onMessage(msg)
currentTime = m.top.videoNode.position
if currentTime > 3 and not m.top.adPlaying
m.top.videoNode.enableTrickPlay = true
end if
end while
end sub
sub setupStreamManager()
m.streamManager.addEventListener(m.sdk.AdEvent.ERROR, errorCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.START, startCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.FIRST_QUARTILE, firstQuartileCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.MIDPOINT, midpointCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.THIRD_QUARTILE, thirdQuartileCallback)
m.streamManager.addEventListener(m.sdk.AdEvent.COMPLETE, completeCallback)
end sub
sub startCallback(ad as object)
print "Callback from SDK -- Start called - "
end sub
sub firstQuartileCallback(ad as object)
print "Callback from SDK -- First quartile called - "
end sub
sub midpointCallback(ad as object)
print "Callback from SDK -- Midpoint called - "
end sub
sub thirdQuartileCallback(ad as object)
print "Callback from SDK -- Third quartile called - "
end sub
sub completeCallback(ad as object)
print "Callback from SDK -- Complete called - "
end sub
sub errorCallback(error as object)
print "Callback from SDK -- Error called - " ; error
m.errorState = True
end sub